프로그래밍 언어/C++

콘솔 앱의 'Main'메서드에서 'async' 수정자를 지정하는 방법

Rateye 2021. 10. 15. 10:51
728x90
반응형
질문 : 콘솔 앱의 'Main'메서드에서 'async'수정자를 지정할 수 없습니다.

async 수정자를 사용한 비동기 프로그래밍이 처음입니다. Main 메서드가 실제로 비동기 적으로 실행되는지 확인하는 방법을 찾으려고합니다.

class Program
{
    static void Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = bs.GetList();
    }
}

public class Bootstrapper {

    public async Task<List<TvChannel>> GetList()
    {
        GetPrograms pro = new GetPrograms();

        return await pro.DownloadTvChannels();
    }
}

나는 이것이 "상단"에서 비동기 적으로 실행되지 않는다는 것을 안다. Main 메서드에 async 한정자를 지정할 수 없기 때문에 main 내에서 비동기식으로 코드를 실행할 수 있습니까?

답변

발견했듯이 VS11에서 컴파일러는 async Main 메서드를 허용하지 않습니다. 이것은 비동기 CTP를 사용하는 VS2010에서 허용되었지만 권장되지는 않았습니다.

특히 비동기 / 대기비동기 콘솔 프로그램 에 대한 최근 블로그 게시물이 있습니다. 다음은 소개 게시물의 배경 정보입니다.

"await"가 awaitable이 완료되지 않은 것을 확인하면 비동기 적으로 작동합니다. 완료되면 메서드의 나머지를 실행하도록 awaitable에 지시 한 다음 비동기 메서드에서 반환합니다. Await는 또한 메서드의 나머지 부분을 awaitable로 전달할 때 현재 컨텍스트를 캡처합니다.

나중에 awaitable이 완료되면 캡처 된 컨텍스트 내에서 나머지 비동기 메서드를 실행합니다.

async Main 있는 콘솔 프로그램에서 이것이 문제인 이유입니다.

소개 게시물에서 비동기 메서드가 완료되기 전에 호출자에게 반환된다는 사실을 기억하십시오. 이것은 UI 응용 프로그램 (메서드가 UI 이벤트 루프로만 반환 됨) 및 ASP.NET 응용 프로그램 (메서드가 스레드를 반환하지만 요청을 활성 상태로 유지)에서 완벽하게 작동합니다. 콘솔 프로그램에서는 잘 작동하지 않습니다. Main이 OS로 돌아가므로 프로그램이 종료됩니다.

한 가지 해결책은 사용자 고유의 컨텍스트를 제공하는 것입니다. 즉, 비동기 호환 가능한 콘솔 프로그램에 대한 "주 루프"입니다.

Async CTP가있는 컴퓨터가있는 경우 My Documents \ Microsoft Visual Studio Async CTP \ Samples (C # Testing) Unit Testing \ AsyncTestUtilities 에서 GeneralThreadAffineContext 를 사용할 수 있습니다. 또는 내 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() 사용에 유의하십시오. Wait() 또는 Result 를 사용하는 경우 발생 AggregateException 래핑을 방지합니다.

업데이트, 2017-11-30 : Visual Studio 2017 업데이트 3 (15.3)부터 해당 언어는 이제 Task 또는 Task<T> 반환 async Main 지원합니다. 이제 다음과 같이 할 수 있습니다.

class Program
{
    static async Task Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = await bs.GetList();
    }
}

의미 체계는 주 스레드를 차단하는 GetAwaiter().GetResult() 스타일과 동일하게 나타납니다. 그러나 아직 C # 7.1에 대한 언어 사양이 없으므로 이는 가정 일뿐입니다.

출처 : https://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main-method-of-a-console-app
728x90
반응형