[C#] async / await 키워드

세동네·2023년 3월 8일
0
post-thumbnail

asyncawait는 비동기 프로그래밍을 보다 손쉽게 지원하기 위해 C# 5.0에 추가된 중요한 기능이다.

· async

async는 메서드를 정의할 때 추가하는 키워드로, 해당 함수가 비동기 함수이며 메서드 안에 await 연산자가 존재함을 알린다. await 연산자는 1개 이상 존재할 수 있고 하나도 없을 수도 있지만, 없을 때는 경고 메시지를 출력한다. async를 표시한다고 해서 자동으로 비동기 방식으로 프로그램을 수행하는 것은 아니고, 일종의 보조 역할을 하는 컴파일러 지시어이다.

async 메서드의 리턴 타입은 대부분 리턴 값이 있으면 Task<TResult>, 없으면 Task 타입인데, 리턴 시 포함하고자 하는 데이터가 String 타입이라면 async Task<String> method() {...}와 같이 정의하고 return "문자열";과 같이 반환하고 싶은 데이터만 반환한다. C# 컴파일러는 반환문의 문자열을 자동으로 Task<String>으로 변환해준다. 또는 async 메서드의 리턴 타입으로 이벤트핸들러를 위한 void 타입을 사용하기도 한다.

· await

메서드 앞의 async 한정자를 확인하면 컴파일러는 메서드 내 await 연산자를 찾는다. 그리고 컴파일러가 그곳에서 메서드를 호출한 호출자에게 제어를 돌려주도록 실행 파일을 만든다. 피연산자의 작업을 비동기로 실행하면서, 해당 피연산자의 비동기 작업이 마무리될 때까지 제어권을 얻은 호출자가 계속 실행될 수 있게 하는 것이다. 비동기 작업이 마무리되면 await 연산자가 해당 작업의 결과를 평가하면서 다음 라인부터 실행을 재개한다.

await의 피연산자로는 Task 또는 Task<T> 객체를 사용한다. 반드시 해당 타입일 필요는 없지만, 내부적으로 반드시 호출해야 하는 GetAwaiter() 메서드를 호출하는 타입이 피연산자여야 한다. 피연산자는 쓰레드 풀에 큐잉되며, 호출자에게 제어를 넘기고 쓰레드 풀 내의 쓰레드에게서 피연산자가 실행되도록 한다. 이때 await 연산자는 현재 피연산자의 비동기 실행이 종료된 후 다음 문장을 이어서 실행하도록 해주는데, 마치 ContinueWith() 메서드로 연결된 것과 같은 방식으로 동작한다.

· 비동기 함수 사용 시 제한 사항

비동기 함수를 사용할 때 다음과 같은 제한이 있음을 알아 두어야 한다.

  1. Main() 메서드, 생성자, 프로퍼티, 이벤트 접근자 메서드는 비동기 함수가 될 수 없다.
  2. 비동기 함수는 out, ref 매개변수를 가질 수 없다.
  3. catch, finally, unsafe 블록 내에서는 await 연산자를 사용할 수 없다.
  4. await 연산자 앞쪽에서 쓰레드의 소유권 및 재귀호출을 허용하는 락을 획득했다가 await 후에 이를 해제할 수 없다. await 이전에 실행되던 쓰레드와 await 이후에 실행되는 쓰레드가 같을 것이란 보장이 없기 때문이다.
  5. 쿼리 표현식 내부에서 from 절의 첫 번째 컬렉션을 나타내는 부분이나 join 절의 컬렉션을 나타내는 부분에서만 await 연산자를 사용할 수 있다.

· 참고

[MS Document] await 연산자
C# 5.0 : async / await 키워드

0개의 댓글