C# 비동기 프로그래밍 패턴과 구현 기법

비동기 프로그래밍의 핵심 개념

C# 5.0의 async/await 키워드는 응답성 높은 애플리케이션 개발을 가능하게 합니다. 비동기 작업은 백그라운드에서 실행되며, 사용자 인터페이스의 응답성을 유지합니다. 주요 구현 패턴으로는 APM, EAP, TAP이 있습니다.

기본 실행 모델 비교

동기식 실행

public delegate int ComputeHandler(int x, int y);
public class Calculator
{
    public static int Multiply(int x, int y)
    {
        Console.WriteLine($"계산 시작: {x} * {y}");
        Thread.Sleep(1500);
        return x * y;
    }
}

public class Program
{
    static void Main()
    {
        ComputeHandler handler = Calculator.Multiply;
        int product = handler(3, 4);
        Console.WriteLine("다른 작업 진행...");
        Console.WriteLine($"결과: {product}");
    }
}

APM(비동기 프로그래밍 모델)

static void Main()
{
    ComputeHandler handler = Calculator.Multiply;
    IAsyncResult asyncResult = handler.BeginInvoke(3, 4, null, null);
    Console.WriteLine("다른 작업 진행...");
    int product = handler.EndInvoke(asyncResult);
    Console.WriteLine($"결과: {product}");
}

이벤트 기반 비동기 패턴(EAP)

static void Main(string[] args)
{
    var stateTracker = new System.Collections.Specialized.HybridDictionary();
    object operationId = "OP_001";
    AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(operationId);
    
    stateTracker[operationId] = asyncOp;
    
    Action<object> backgroundWork = delegate
    {
        // 장시간 실행 작업
        asyncOp.Post(delegate
        {
            Console.WriteLine("작업 완료");
            stateTracker.Remove(operationId);
        }, null);
    };
    
    asyncOp.Post(backgroundWork, null);
    Console.WriteLine("주 스레드 작업 계속");
}

태스크 기반 비동기 패턴(TAP)

static async Task Main()
{
    Console.WriteLine("메인 스레드 시작");
    await ExecuteAsyncProcess();
    Console.WriteLine("메인 스레드 종료");
}

static async Task ExecuteAsyncProcess()
{
    Console.WriteLine("비동기 작업 시작");
    await Task.Run(() => 
    {
        for(int i = 0; i < 3; i++)
        {
            Console.WriteLine($"작업 진행 {i}");
            Task.Delay(500).Wait();
        }
    });
    Console.WriteLine("비동기 작업 완료");
}

비동기 프로그래밍 핵심 기술

작업 생성 및 실행

static string GenerateMessage(string name)
{
    Thread.Sleep(2000);
    return $"Hello, {name}";
}

static Task<string> GenerateMessageAsync(string name)
{
    return Task.Run(() => GenerateMessage(name));
}

비동기 연쇄 실행

async Task ProcessSequentially()
{
    string msg1 = await GenerateMessageAsync("Kim");
    string msg2 = await GenerateMessageAsync("Lee");
    Console.WriteLine($"{msg1}\n{msg2}");
}

병렬 작업 처리

async Task ProcessInParallel()
{
    Task<string> t1 = GenerateMessageAsync("Kim");
    Task<string> t2 = GenerateMessageAsync("Lee");
    
    await Task.WhenAll(t1, t2);
    Console.WriteLine($"{t1.Result}\n{t2.Result}");
}

예외 처리 메커니즘

async Task HandleErrors()
{
    try
    {
        Task faultyTask = SimulateErrorAsync();
        Task normalTask = GenerateMessageAsync("Park");
        await Task.WhenAll(faultyTask, normalTask);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"오류 발생: {ex.Message}");
    }
}

작업 취소 기능

async Task ProcessWithCancellation(CancellationToken token)
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Task.Delay(500).Wait();
        }
    }, token);
}

실행 모드 유형

  • 대기 모드: 비동기 작업 완료까지 블로킹
  • 폴링 모드: 주기적 완료 여부 확인
  • 콜백 모드: 작업 완료 시 이벤트 기반 통지

태그: C# 비동기-프로그래밍 async-await Task APM

6월 16일 19:42에 게시됨