[C# 동시성 프로그래밍] - 비동기 프로그래밍

참고

  • C# 동시성 프로그래밍

비동기 프로그래밍 이점

  • 비동기 프로그래밍은 크게 두 가지 이점이 있습니다.
  • 첫 번째로 최종 사용자용 GUI 프로그램은 비동기 프로그래밍을 통해 응답성을 확보할 수 있습니다.
  • 작업을 실행하는 동안 일시적으로 GUI가 잠기는 프로그램을 사용해 보았을 것입니다.
  • 비동이 프로그램이라면 작업 중에도 사용자 입력에 반응할 수 있습니다.
  • 두 번째로 서버 프로그램은 비동기 프로그래밍을 통해 규모를 변경할 수 있습니다.
  • 서버 애플리케이션은 스레드 풀만 사용해도 어느 정도 규모를 변경할 수 있지만, 비동기 서버 애플리케이션은 대개 훨씬 큰 단위로 규모를 변경할 수 있습니다.

비동기 프로그래밍 특징

  • 위에서 설명한 비동기 프로그래밍의 두 가지 이점은 모두 비동기 프로그래밍이 스레드를 가로막지 않고 자유롭게 풀어 준다는 특징을 바탕으로 합니다.
  • GUI 프로그램에서 비동기 프로그래밍은 UI 스레드를 자유롭게 풀어 줍니다.
  • 따라서 GUI 애플리케이션은 사용자 입력에 응답성을 유지할 수 있습니다.
  • 서버 애플리케이션에서 비동기 프로그래밍은 요청 스레드를 자유롭게 풀어 줍니다.
  • 따라서 서버는 자신의 스레드를 사용해서 더 많은 요청을 처리할 수 있습니다.

.NET 비동기 프로그래밍

  • 최신 비동기 닷넷 애플리케이션은 async와 awit, 두 가지 키워드를 사용하여 비동기 프로그래밍을 표현할 수 있습니다.
  • 메서드 선언에 추가하는 async 키워드는 두 가지 목적을 지닙니다.
    • 메서드 안에서 await 키워드를 사용할 수 있게 하고, 컴파일러에 해당 메서드의 상태 머신을 생성하라고 지시 합니다.
    • yield 가 작업을 반환하는 방식과 비슷합니다.
    • async 메서드는 값을 반환해야 할 때는 Task를 반환하고, 값을 반환하지 않을 때는 Task 또는 ValueTask 같은 유사 Task 형식을 반환합니다.
    • 또 async 메서드는 열거형에 속하는 여러 값을 반환해야 할 때 IAsyncEnumerable<T>IAsyncEnumerator<T> 를 반환할 수 있습ㄴ디ㅏ.

      async void는 사용하지 말아야 합니다. void를 반환하는 aysnc 메서드도 있을 수 있지만, async 이벤트 핸들러를 작성할 때만 사용해야 합니다. 보통 반환 값이 없는 async 메서드는 void가 아닌 Task를 반환해야 합니다.


간단 예제

  • 위 개념을 바탕으로 간단한 예제 코드를 작성해 보겠습니다.
async Task DoSomethingASync()
{
    int value = 13;

    // 비동기적으로 1초를 대기한다.
    await Task.Delay(TimeSpan.FromSeconds(1));

    value *= 2;

    // 비동기적으로 1초를 대기한다.
    await Task.Delay(TimeSpan.FromSeconds(1));

    Console.WriteLine(value);
}
  • async 메서드는 다른 메서드와 마찬가리조 동기적으로 실행하기 전에 시작합니다.
  • async 메서드 안의 await 키워드는 인수로 지정한 만큼 비동기적으로 대기합니다.
  • 먼저 작업이 이미 끝났는지 확인하고 끝났으면 동기적으로 실행을 계속 합니다.
  • 아니면, async 메서드를 일시 정지하고 불완전한 작업을 반환합니다. 얼마 후에 작업이 끝나면 async 메서드의 실행을 재개합니다.

async 메서드 실행 순서

  • 흔히 awiat로 작업을 기다리거나 await가 메서드를 일시 정지하기로 하면 컨텍스르를 저장합니다.
  • 널이 아니면 현재 SynchronizationContext를 저장하고, 이때 컨텍스트는 현재 TaskScheduler 입니다.
  • 메서드는 저장한 컨텍스트 안에서 실행을 재개합니다.
  • 대개 이 컨텍스트는 UI 스레드에서 호출했으면 UI 컨텍스트 이고, 다른 상황이라면 스레드 풀 컨테스트입니다.
  • 코어 버전의 ASP.NET 클래식 애플리케이션이면 ASP.NET 요청 컨텍스트 일 수도 있습니다.
  • 따라서 앞의 예제 코드에서 모든 동기적 부분은 원래 컨텍스트에서 실행을 재개하려고 시도합니다.
  • DoSomethingASync를 UI 스레드에서 호출하면 각 동기적 부분을 UI 스레드에서 실행하지만, 스레드 풀 스레드에서 호출하면 각 동기적 부분을 스레드 풀 스레드에서 실행합니다.
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY