알다시피 VS11에서 컴파일러는 async Main
메소드 를 허용하지 않습니다 . 이것은 비동기 CTP와 함께 VS2010에서 허용되었지만 권장되지는 않았습니다.
async / await 및 비동기 콘솔 프로그램 에 대한 최근 블로그 게시물이 있습니다 . 소개 게시물의 배경 정보는 다음과 같습니다.
"await"는 awaitable이 완료되지 않은 것으로 보이면 비동기 적으로 작동합니다. 완료 될 때 메소드의 나머지를 실행하도록 awaitable에 지시 한 다음 async 메소드에서 리턴합니다 . Await는 메소드의 나머지를 awaitable에 전달할 때 현재 컨텍스트를 캡처합니다 .
나중에 Awaitable이 완료되면 나머지 캡처 방법 (캡처 된 컨텍스트 내)을 실행합니다.
이것이 콘솔 프로그램에서 문제가되는 이유입니다 async Main
.
소개 게시물에서 비동기 메소드 는 완료되기 전에 호출자로 돌아갑니다 . 이것은 UI 응용 프로그램 (메소드 이벤트가 UI 이벤트 루프로 돌아옴) 및 ASP.NET 응용 프로그램 (메서드가 스레드를 반환하지만 요청은 계속 유지)에서 완벽하게 작동합니다. 콘솔 프로그램의 경우 제대로 작동하지 않습니다. Main이 OS로 돌아가므로 프로그램이 종료됩니다.
하나의 솔루션은 비동기 호환 콘솔 프로그램을위한 "메인 루프"라는 고유 한 컨텍스트를 제공하는 것입니다.
당신은 비동기 CTP와 기계가있는 경우 사용할 수 있습니다 GeneralThreadAffineContext
에서 내 문서 \ 마이크로 소프트 비주얼 스튜디오 비동기 CTP \ 샘플 (C # 테스트) 단위 테스트 \ AsyncTestUtilities . 또는 내 Nito.AsyncEx NuGet 패키지AsyncContext
에서 사용할 수 있습니다 .
다음은 AsyncContext
;을 사용하는 예입니다 . GeneralThreadAffineContext
거의 동일한 사용법이 있습니다.
using Nito.AsyncEx;
class Program
{
static void Main(string[] args)
{
AsyncContext.Run(() => MainAsync(args));
}
static async void MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
또는 비동기 작업이 완료 될 때까지 기본 콘솔 스레드를 차단할 수 있습니다.
class Program
{
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
GetAwaiter().GetResult()
; 의 사용에 유의하십시오 . 이것은 피할 AggregateException
사용하면 어떻게 포장 Wait()
또는 Result
.
업데이트, 2017년 11월 30일 : 비주얼 스튜디오 2017 업데이트 3 (15.3) 현재로는, 언어는 지금 지원 async Main
- 한이 반환로 Task
또는 Task<T>
. 이제이 작업을 수행 할 수 있습니다.
class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}
시맨틱 GetAwaiter().GetResult()
은 메인 스레드를 차단하는 스타일과 동일한 것으로 보입니다 . 그러나 C # 7.1에 대한 언어 사양은 아직 없으므로 가정에 불과합니다.