[C#] invoke

동키·2024년 12월 26일

C#

목록 보기
11/12

Invoke는 C#에서 다양한 용도로 사용되며, 문맥에 따라 동작 방식이 조금씩 다릅니다. 주요 사용 사례는 델리게이트 호출, UI 스레드 호출 등이 있습니다.


델리게이트(Delegate)에서 Invoke

  • 델리게이트는 메서드를 참조하는 객체입니다.
  • Invoke를 사용하면 델리게이트에 연결된 메서드를 실행할 수 있습니다.
  • 델리게이트를 호출할 때 동기적으로 실행됩니다.
using System;

class Program
{
    delegate int MyDelegate(int x, int y);

    static void Main()
    {
        MyDelegate del = Add;

        // Invoke를 사용하여 메서드 실행
        int result = del.Invoke(3, 5);
        Console.WriteLine($"Result: {result}"); // 출력: Result: 8

        // Invoke를 생략하고 호출 (동일한 결과)
        result = del(3, 5);
        Console.WriteLine($"Result: {result}"); // 출력: Result: 8
    }

    static int Add(int a, int b)
    {
        return a + b;
    }
}

동작 과정

  1. del.Invoke(3, 5)를 호출하면 델리게이트가 참조하는 Add 메서드가 실행됩니다.
  2. 델리게이트 호출은 Invoke 메서드 호출로 컴파일됩니다.
  3. Invoke 없이도 축약된 형태로 호출 가능합니다 (del(3, 5))

UI 스레드에서 Invoke

문제점

  • Windows Forms 및 WPF 애플리케이션에서는 UI 스레드와 작업 스레드가 분리되어 있습니다.
  • 작업 스레드에서 UI를 직접 수정하려고 하면 InvalidOperationException이 발생합니다.

해결 방법

  • Invoke를 사용하여 UI 스레드에서 안전하게 작업할 수 있습니다.
  • Control.Invoke(Windows Forms) 또는 Dispatcher.Invoke(WPF)를 사용합니다.
// Windows Forms
using System;
using System.Threading;
using System.Windows.Forms;

class Program : Form
{
    private Label label;

    public Program()
    {
        label = new Label { Text = "Initial Text", Dock = DockStyle.Fill };
        Controls.Add(label);

        // 백그라운드 스레드에서 UI 업데이트 시도
        Thread backgroundThread = new Thread(UpdateLabelText);
        backgroundThread.Start();
    }

    private void UpdateLabelText()
    {
        Thread.Sleep(2000); // 2초 대기

        // UI 스레드에서 안전하게 업데이트
        this.Invoke((MethodInvoker)delegate
        {
            label.Text = "Updated Text from Background Thread!";
        });
    }

    [STAThread]
    static void Main()
    {
        Application.Run(new Program());
    }
}

동작 과정

  • 백그라운드 스레드가 UpdateLabelText 메서드를 실행합니다.
  • this.Invoke를 사용하여 UI 스레드에서 label.Text를 업데이트합니다.
  • UI 스레드는 안전하게 작업을 수행합니다.

Invoke와 BeginInvoke의 차이

특징InvokeBeginInvoke
실행 방식동기적(Synchronous): 호출이 끝날 때까지 대기.비동기적(Asynchronous): 즉시 반환.
대기 여부호출이 완료될 때까지 호출자가 대기.호출자가 기다리지 않고 실행을 계속함.
사용 예UI 업데이트, 즉각적인 작업 처리.백그라운드 작업 또는 비동기 UI 업데이트.
using System;
using System.Threading;
using System.Windows.Forms;

class Program : Form
{
    private Label label;

    public Program()
    {
        label = new Label { Text = "Initial Text", Dock = DockStyle.Fill };
        Controls.Add(label);

        Thread backgroundThread = new Thread(() =>
        {
            Thread.Sleep(2000);

            // 동기적 UI 업데이트
            this.Invoke((MethodInvoker)(() => label.Text = "Updated using Invoke"));

            // 비동기적 UI 업데이트
            this.BeginInvoke((MethodInvoker)(() => label.Text = "Updated using BeginInvoke"));
        });

        backgroundThread.Start();
    }

    [STAThread]
    static void Main()
    {
        Application.Run(new Program());
    }
}

동작

  • Invoke: UI 업데이트를 동기적으로 실행.
  • BeginInvoke: UI 업데이트를 비동기적으로 실행.
profile
오키동키

0개의 댓글