콘솔 앱의 '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();
}
}
저는 이것이 "위"에서 비동기식으로 실행되지 않는다는 것을 알고 있습니다.할 수 없기 입니다.async
의수어의 Main
메소드, 코드를 실행하려면 어떻게 해야 합니까?main
비동기식으로?
발견한 에서는 컴파일러가 VS11을 .async Main
방법. 이은 비동기 CTP를는 않습니다이 기능은 비동기 CTP를 사용하는 VS2010에서 허용되었지만 권장되지는 않았습니다.
업데이트, 2017-11-30: Visual Studio 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에 대한 언어 사양은 아직 없으므로 이는 가정에 불과합니다.
저는 특히 비동기/대기 및 비동기 콘솔 프로그램에 대한 최근 블로그 게시물을 가지고 있습니다.소개 게시물의 배경 정보는 다음과 같습니다.
대기가 완료되지 않은 것을 "대기"가 확인하면 비동기식으로 작동합니다.이 명령은 메서드가 완료되면 나머지 메서드를 실행하도록 대기자에게 지시한 다음 비동기 메서드에서 반환합니다.또한 Wait는 메서드의 나머지 부분을 Waitable에게 전달할 때 현재 컨텍스트를 캡처합니다.
나중에 대기가 완료되면 (캡처된 컨텍스트 내에서) 비동기 메서드의 나머지를 실행합니다.
에서 이 가 발생하는 여기에 .async Main
:
소개 게시물에서 비동기 메서드가 완료되기 전에 호출자에게 다시 전송된다는 것을 기억하십시오.이는 UI 애플리케이션(메소드가 UI 이벤트 루프로 되돌아옴) 및 ASP에서 완벽하게 작동합니다.NET 응용 프로그램(메소드는 스레드에서 반환되지만 요청을 활성 상태로 유지함).기본 프로그램이 OS로 돌아가기 때문에 프로그램이 종료됩니다.
한 가지 해결책은 비동기식 콘솔 프로그램의 "메인 루프"인 사용자 고유의 컨텍스트를 제공하는 것입니다.
이 있는 에는 "CTP"를 할 수 .GeneralThreadAffineContext
My Documents\Microsoft Visual Studio 비동기 CTP\샘플(C# 테스트) 장치 테스트\비동기 테스트 유틸리티.대신에, 당신은 내 니토에서 사용해도 됩니다.AsyncEx NuGet 패키지입니다.
여기에 다은을사예입다니한을 사용한 .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
▁you랩▁▁if를 사용하면 하는 랩핑Wait()
또는Result
.
이 간단한 구성으로 이 문제를 해결할 수 있습니다.
class Program
{
static void Main(string[] args)
{
Task.Run(async () =>
{
// Do any async anything you need here without worry
}).GetAwaiter().GetResult();
}
}
이렇게 하면 원하는 스레드 풀에서 수행하는 모든 작업이 실행되고(시작/대기 중인 다른 작업이 스레드에 다시 참여하지 않도록) 콘솔 앱을 닫기 전에 모든 작업이 완료될 때까지 기다립니다.특수 루프 또는 외부 립이 필요하지 않습니다.
편집: 발견되지 않은 예외에 대한 Andrew의 솔루션을 통합합니다.
다음을 수행하여 외부 라이브러리 없이도 이 작업을 수행할 수 있습니다.
class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var getListTask = bs.GetList(); // returns the Task<List<TvChannel>>
Task.WaitAll(getListTask); // block while the task completes
var list = getListTask.Result;
}
}
C# 7.1에서는 적절한 비동기 메인을 수행할 수 있습니다.다음에 대한 적합한 서명Main
메서드가 다음으로 확장되었습니다.
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
예를 들어 다음 작업을 수행할 수 있습니다.
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
컴파일 시 비동기 진입점 메서드가 호출로 변환됩니다.GetAwaitor().GetResult()
.
세부 정보: https://blogs.msdn.microsoft.com/mazhou/2017/05/30/c-7-series-part-2-async-main
편집:
C# 7.1 언어 기능을 사용하려면 프로젝트를 마우스 오른쪽 단추로 클릭하고 "속성"을 클릭한 다음 "빌드" 탭으로 이동해야 합니다.여기서 하단의 고급 단추를 클릭합니다.
언어 버전 드롭다운 메뉴에서 "7.1"(또는 더 높은 값)을 선택합니다.
기본값은 콘솔 앱에서 비동기 메인을 지원하지 않는 C# 7.0으로 평가하는 "최신 메이저 버전"입니다.
다른 모든 답변이 간과한 중요한 기능을 추가하겠습니다. 바로 취소입니다.
TPL의 큰 점 중 하나는 취소 지원이며, 콘솔 앱에는 취소 방법(CTRL+C)이 내장되어 있습니다.그것들을 묶는 것은 매우 간단합니다.모든 비동기 콘솔 앱을 구성하는 방법은 다음과 같습니다.
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
System.Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
MainAsync(args, cts.Token).GetAwaiter.GetResult();
}
static async Task MainAsync(string[] args, CancellationToken token)
{
...
}
C# 7.1(2017 업데이트 3과 비교하여 사용)에 비동기 메인이 도입됨
다음과 같이 쓸 수 있습니다.
static async Task Main(string[] args)
{
await ...
}
업데이트:
컴파일 오류가 발생할 수 있습니다.
프로그램에 진입점에 적합한 정적 '기본' 메서드가 없습니다.
이 오류는 vs2017.3이 기본적으로 c#7.1이 아닌 c#7.0으로 구성되어 있기 때문입니다.
프로젝트 설정을 명시적으로 수정하여 c#7.1 기능을 설정해야 합니다.
다음 두 가지 방법으로 c#7.1을 설정할 수 있습니다.
방법 1: 프로젝트 설정 창 사용:
- 프로젝트 설정 열기
- 빌드 탭 선택
- 고급 단추를 클릭
- 다음 그림과 같이 원하는 버전을 선택합니다.
방법 2: .csproj의 속성 그룹을 수동으로 수정합니다.
이 속성 추가:
<LangVersion>7.1</LangVersion>
예:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
C# 7.1 이상을 사용하는 경우, nawfal의 답변으로 이동하고 기본 메소드의 반환 유형을 다음으로 변경합니다.Task
또는Task<int>
그렇지 않은 경우:
- 가다를 .
async Task MainAsync
요한의 말대로. - 정결라고 요!
.GetAwaiter().GetResult()
do0g가 말한 것처럼 근본적인 예외를 잡기 위해. - 코리가 말한 것처럼 지원 취소.
- 번째 깐잠.
CTRL+C
프로세스를 즉시 종료해야 합니다. (감사합니다!) - 들
OperationCancelledException
적절한 오류 코드를 반환합니다.
최종 코드는 다음과 같습니다.
private static int Main(string[] args)
{
var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = !cts.IsCancellationRequested;
cts.Cancel();
};
try
{
return MainAsync(args, cts.Token).GetAwaiter().GetResult();
}
catch (OperationCanceledException)
{
return 1223; // Cancelled.
}
}
private static async Task<int> MainAsync(string[] args, CancellationToken cancellationToken)
{
// Your code...
return await Task.FromResult(0); // Success.
}
아직 이렇게 많이 필요하지는 않았지만 콘솔 애플리케이션을 사용하여 빠른 테스트를 수행하고 비동기화를 요구하면 다음과 같이 해결할 수 있습니다.
class Program
{
static void Main(string[] args)
{
MainAsync(args).Wait();
}
static async Task MainAsync(string[] args)
{
// Code here
}
}
기본에서 비동기식으로 태스크를 호출하는 경우 사용
작업. 실행():NET 4.5
작업. 공장.의 경우 새로 만들기()를 시작합니다.NET 4.0(Microsoft가 필요할 수 있음).비동기 및 대기 키워드에 대한 Bcl.Async 라이브러리)
세부 정보: http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
기본적으로 GetList에 대한 통화를 다음으로 변경합니다.
Task.Run(() => bs.GetList());
C# 5 CTP가 도입되었을 때, 당신은 확실히 메인을 다음과 같이 표시할 수 있었습니다.async
비록 그렇게 하는 것이 일반적으로 좋은 생각은 아니었지만.VS 2013 출시로 인해 오류가 발생하여 변경된 것 같습니다.
다른 포그라운드 스레드를 시작하지 않은 경우 프로그램이 종료됩니다.Main
백그라운드 작업을 시작한 경우에도 완료됩니다.
당신은 정말 무엇을 하려고 합니까?참고로 당신의GetList()
메소드는 현재 비동기식일 필요가 없습니다. 즉, 실제 이유 없이 계층을 추가하는 것입니다.이는 논리적으로 다음과 같습니다(보다 더 복잡합니다.
public Task<List<TvChannel>> GetList()
{
return new GetPrograms().DownloadTvChannels();
}
C# - C# 7.1의 최신 버전을 통해 비동기 콘솔 앱을 만들 수 있습니다.를 15을 프젝트에 C# 7.1을를 VS로 15.3이고 C#버으다변으로 .C# 7.1
또는C# latest minor version
이렇게 하려면 프로젝트 속성 -> 빌드 -> 고급 -> 언어 버전으로 이동합니다.
이 후에는 다음 코드가 작동합니다.
internal class Program
{
public static async Task Main(string[] args)
{
(...)
}
C# 7.1 기준으로 이 방법에 대해 다음과 같은 서명이 유효합니다.
public static void Main() { }
public static int Main() { }
public static void Main(string[] args) { }
public static int Main(string[] args) { }
public static async Task Main() { }
public static async Task<int> Main() { }
public static async Task Main(string[] args) { }
public static async Task<int> Main(string[] args) { }
이제 비동기/대기 기능을 사용할 수 있습니다.
static async Task Main(string[] args)
{
Console.WriteLine("Hello Asyn Main method!");
await Task.Delay(200);
}
MSDN의 경우 작업에 대한 설명서입니다.Run Method(Action)는 메서드를 비동기적으로 실행하는 방법을 보여주는 예제를 제공합니다.main
:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
ShowThreadInfo("Application");
var t = Task.Run(() => ShowThreadInfo("Task") );
t.Wait();
}
static void ShowThreadInfo(String s)
{
Console.WriteLine("{0} Thread ID: {1}",
s, Thread.CurrentThread.ManagedThreadId);
}
}
// The example displays the following output:
// Application thread ID: 1
// Task thread ID: 3
예제 다음에 나오는 이 문장에 유의하십시오.
예제에서는 비동기 작업이 기본 응용 프로그램 스레드와 다른 스레드에서 실행됨을 보여 줍니다.
따라서 작업을 기본 응용 프로그램 스레드에서 실행하려면 @StephenClearary의 답변을 참조하십시오.
또한 작업이 실행되는 스레드와 관련하여 Stephen의 답변에 대한 코멘트도 기록합니다.
간단한 것을 사용할 수 있습니다.
Wait
또는Result
그리고 그것에는 아무런 문제가 없습니다. 여기에는 두 한 차이점이 합니다: 1) 하 두 만 가 지 중 모 차 있 것 두 명 요 세 을 심 하 는 다 이 이 점 한 요 지 ▁1 ) : 1) 모async
스레드가 되며, 2) 연은속주스아실풀행며되에모, 2)는다같포이장다니됩과음예외든으로 .AggregateException
.
(예외 처리를 통합하여 다음을 처리하는 방법은 예외 처리(Task Parallel Library)를 참조하십시오.AggregateException
.)
마지막으로 작업 설명서의 MSDN에 대해 설명합니다.다음 예에서는 값을 반환하는 비동기 작업을 실행하는 방법을 보여 줍니다.
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var t = Task.Run(async delegate
{
await Task.Delay(TimeSpan.FromSeconds(1.5));
return 42;
});
t.Wait();
Console.WriteLine("Task t Status: {0}, Result: {1}",
t.Status, t.Result);
}
}
// The example displays the following output:
// Task t Status: RanToCompletion, Result: 42
를 통 하 는 대신과▁a를 전달하는 하세요.delegate
Task.Run
대신 다음과 같은 람다 함수를 전달할 수 있습니다.
var t = Task.Run(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(1.5));
return 42;
});
저의 경우, 제가 주로 사용하는 방법에서 비동기식으로 실행하고 싶었던 작업 목록이 있었고, 꽤 오랫동안 프로덕션에서 사용해 왔으며 잘 작동합니다.
static void Main(string[] args)
{
Task.Run(async () => { await Task.WhenAll(jobslist.Select(nl => RunMulti(nl))); }).GetAwaiter().GetResult();
}
private static async Task RunMulti(List<string> joblist)
{
await ...
}
현재 스레드(대기 중에 고착됨)의 재결합을 시도하는 함수를 호출 스택 아래 어딘가에서 호출할 때 중지를 방지하려면 다음 작업을 수행해야 합니다.
class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
List<TvChannel> list = Task.Run((Func<Task<List<TvChannel>>>)bs.GetList).Result;
}
}
(출연진은 모호성을 해결하기 위해서만 필요함)
class Program
{
public static EventHandler AsyncHandler;
static void Main(string[] args)
{
AsyncHandler+= async (sender, eventArgs) => { await AsyncMain(); };
AsyncHandler?.Invoke(null, null);
}
private async Task AsyncMain()
{
//Your Async Code
}
}
이것은 가상적이지만 저는 생각하고 있습니다.
static void Main(string[] args)
{
var context = new Thread(() => /*do stuff*/);
context.Start();
context.Join();
}
이것이 당신이 찾고 있는 것인지 확실하지 않지만, 저는 로딩 중인 방법을 기다리고 싶었습니다.결국 Main_Show 핸들러를 사용하여 비동기화했습니다.
private async void Main_Shown(object sender, EventArgs e)
{
await myAsyncMethod();
}
언급URL : https://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main-method-of-a-console-app
'programing' 카테고리의 다른 글
https Firefox를 통해 액세스할 때 Azure 웹 사이트에서 SEC_ERROR_OCSP_INVALID_SIGNING_CERT를 반환합니다. (0) | 2023.05.08 |
---|---|
pg_restore를 실행할 때 "[archiver] 지원되지 않는 버전(1.13) 파일 헤더"를 가져오는 중 (0) | 2023.05.08 |
C#에서 환경 변수를 가져오고 설정하는 방법은 무엇입니까? (0) | 2023.05.08 |
문자열을 날짜/시간으로 변환 (0) | 2023.05.08 |
Postgre에서 'user'라는 이름의 데이터베이스 테이블을 만들 수 없습니다.SQL (0) | 2023.05.08 |