이것은 “대기없이 C #에서 비동기 메서드를 안전하게 호출하는 방법” 과 중복되지 않습니다 .
다음 경고를 어떻게 잘 억제합니까?
경고 CS4014 :이 호출을 기다리지 않으므로 호출이 완료되기 전에 현재 메소드의 실행이 계속됩니다. ‘await’연산자를 호출 결과에 적용하십시오.
간단한 예 :
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
내가 시도하고 싫어했던 것 :
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
업데이트 때문에, 원래의 허용 대답은 편집 된, 나는에 허용 대답을 변경 한 C 7.0 폐기 # 사용하여 하나의 내가 생각하지 않는 한, ContinueWith
여기에 적합하다. 화재 및 잊어 버린 작업에 대한 예외를 기록해야 할 때마다 Stephen Cleary가 제안한 보다 정교한 접근 방식을 사용합니다 .
답변
답변
경고를 방지하는 확장 방법을 만들 수 있습니다. 확장 메소드는 비어 있거나 예외 처리를 추가 할 수 있습니다 .ContinueWith()
.
static class TaskExtensions
{
public static void Forget(this Task task)
{
task.ContinueWith(
t => { WriteLog(t.Exception); },
TaskContinuationOptions.OnlyOnFaulted);
}
}
public async Task StartWorkAsync()
{
this.WorkAsync().Forget();
}
그러나 ASP.NET 은 실행중인 작업 수를 계산하므로 Forget()
위에 나열된 간단한 확장명 에서는 작동하지 않으며 예외로 인해 실패 할 수 있습니다.
비동기 작업이 여전히 보류중인 동안 비동기 모듈 또는 핸들러가 완료되었습니다.
.NET 4.5.2에서는 HostingEnvironment.QueueBackgroundWorkItem
다음 을 사용하여 해결할 수 있습니다 .
public static Task HandleFault(this Task task, CancellationToken cancelToken)
{
return task.ContinueWith(
t => { WriteLog(t.Exception); },
cancelToken,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.Default);
}
public async Task StartWorkAsync()
{
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(
cancelToken => this.WorkAsync().HandleFault(cancelToken));
}
답변
다음 속성을 사용하여 메소드를 장식 할 수 있습니다.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:Await.Warning")]
static async Task StartWorkAsync()
{
WorkAsync();
// ...
}
기본적으로 컴파일러는 수행중인 작업을 알고 있으며 가능한 실수에 대해 걱정할 필요가 없다는 것을 컴파일러에 알리고 있습니다.
이 코드의 중요한 부분은 두 번째 매개 변수입니다. “CS4014 :”부분은 경고를 억제하는 것입니다. 당신은 나머지에 원하는 것을 쓸 수 있습니다.
답변
이것을 다루는 두 가지 방법.
삭제 변수 (C # 7)에 저장
예
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);
C # 7에서 폐기가 도입되었으므로 경고를 억제하는 것보다 낫다고 생각합니다. 경고를 억제 할뿐만 아니라 화재와 잊어 버린 의도를 분명하게하기 때문입니다.
또한 컴파일러는 릴리스 모드에서 최적화 할 수 있습니다.
그냥 억제
#pragma warning disable 4014
...
#pragma warning restore 4014
“화재하고 잊어 버리기”에 충분한 솔루션입니다
이 경고가 존재하는 이유는 많은 경우 태스크를 기다리지 않고 태스크를 리턴하는 메소드를 사용하려는 의도가 아니기 때문입니다. 발사하고 잊어 버릴 때 경고를 억제하는 것이 좋습니다.
철자법을 기억하는 데 어려움이 있다면 #pragma warning disable 4014
Visual Studio에서 추가하십시오. Ctrl +를 누르십시오. “Quick Actions”를 연 다음 “Suppress CS2014″를 엽니 다.
전부
경고를 억제하기 위해 몇 번의 틱을 실행하는 메소드를 작성하는 것은 어리 석습니다.
답변
경고를 중지하는 쉬운 방법은 작업을 호출 할 때 간단히 작업을 할당하는 것입니다.
Task fireAndForget = WorkAsync(); // No warning now
그리고 원래 게시물에서 다음을 수행합니다.
static async Task StartWorkAsync()
{
// Fire and forget
var fireAndForget = WorkAsync(); // Tell the compiler you know it's a task that's being returned
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
답변
경고의 이유는 WorkAsync가 Task
읽거나 기다리지 않은 것을 반환하기 때문입니다. WorkAsync의 반환 유형을로 설정하면 void
경고가 사라집니다.
일반적으로 Task
호출자가 작업자의 상태를 알아야 할 때 메소드가를 반환합니다 . fire-and-forget의 경우, 호출자가 호출 된 메소드와 독립적임을 나타 내기 위해 void를 리턴해야합니다.
static async void WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // no warning since return type is void
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
답변
void를 반환하는 비동기 메서드 안에 래핑하지 않겠습니까? 약간 길지만 모든 변수가 사용됩니다.
static async Task StartWorkAsync()
{
async void WorkAndForgetAsync() => await WorkAsync();
WorkAndForgetAsync(); // no warning
}