C#에서의 위임, 이벤트, 동기 및 비동기 처리 개념 정리

위임(Delegate)의 기본 구조

위임은 특정 반환 타입과 매개변수 시그니처를 가진 메서드를 참조할 수 있는 형식이다. 이는 함수 포인터와 유사하지만, 타입 안전성을 갖춘 객체 기반의 구현이다.

public delegate void MessageHandler(string message);

이 위임을 사용해 인스턴스를 생성하고, 적절한 메서드를 연결할 수 있다.

MessageHandler handler = new MessageHandler(DisplayMessage);

private void DisplayMessage(string msg)
{
    MessageBox.Show(msg);
}

위임은 Invoke 또는 BeginInvoke를 통해 호출되며, 후자는 비동기 실행을 가능하게 한다.

handler.BeginInvoke("메시지 전달 완료", null, null);

또한 람다 표현식이나 익명 메서드를 활용해 간결하게 위임을 정의할 수 있다.

MessageHandler simpleHandler = (msg) => Console.WriteLine($"처리: {msg}");
simpleHandler("간단한 메시지");

이벤트(Event)의 역할과 설계

이벤트는 위임을 기반으로 한 특수한 형태로, 클래스 내부에서만 발생시키는 것이 원칙이다. 이는 정보 은닉과 안정성 향상을 위해 설계되었다.

public event MessageHandler OnMessageReceived;

외부 코드는 이벤트에 대한 등록만 가능하며, 직접 발행할 수 없다. 예를 들어, 프로세스 종료 시 이벤트를 발생시키는 경우:

process.Exited += (sender, args) => {
    Console.WriteLine("프로세스 종료됨");
};

이벤트는 주로 EventHandler<TEventArgs> 또는 커스텀 위임을 통해 정의되며, 발생 시 발생자와 관련된 데이터를 전달할 수 있다.

위임과 이벤트의 차이점

  • 위임: 어디서든 InvokeBeginInvoke로 호출 가능. 자유도가 높지만, 과도한 사용은 결합도 증가로 이어질 수 있음.
  • 이벤트: 클래스 내부에서만 raise 가능. 외부로부터의 무분별한 호출을 방지하여 안정적인 통신 모델을 제공.

비동기 처리와 위임의 관계

위임은 비동기 처리를 위한 핵심 도구 중 하나이다. BeginInvoke는 스레드 풀을 이용해 백그라운드 스레드에서 작업을 수행한다.

handler.BeginInvoke("비동기 메시지", callback => {
    Console.WriteLine("작업 완료");
}, null);

이 방식은 직접 ThreadThreadPool를 다루는 것보다 더 간편하며, 콜백 기반의 제어 흐름을 제공한다.

Task를 통한 고급 비동기 처리

.NET Framework 4 이후, System.Threading.Tasks.Task는 비동기 작업의 중심이 되었다. 이는 스레드 풀 기반으로 동작하며, 복잡한 의존성 관리와 취소 기능을 지원한다.

Task.Run(() => {
    Console.WriteLine($"작업 스레드 ID: {Task.CurrentId}");
    // 긴 작업 수행
});

여러 가지 시작 방법이 있으며, TaskFactory.StartNew, new Task(...)Start() 호출 등이 있다.

// TaskFactory 사용
var task1 = TaskFactory.StartNew(() => DoWork());

// Task 생성 후 시작
var task2 = new Task(() => DoWork());
task2.Start();

// 동기 실행 (대기)
task2.RunSynchronously();

TaskCreationOptions를 통해 작업의 특성을 명시할 수 있다. 예를 들어, LongRunning은 장시간 실행 작업임을 알리고, 새 스레드 할당을 요청할 수 있다.

Action과 Func의 활용

제네릭 위임인 ActionFunc는 코드를 더욱 간결하게 만든다.

// Action: 반환 없음, 매개변수 가능
Action<string> print = msg => Console.WriteLine(msg);
print("안녕하세요");

// Func: 반환 있음, 최대 16개의 매개변수까지 지원
Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 3);
Console.WriteLine(result);

이러한 구문은 람다와 함께 사용하면 매우 효율적이고 가독성이 뛰어난 코드를 작성할 수 있다.

태그: Delegate Event Task async threading

5월 30일 16:04에 게시됨