“경고 CS4014 :이 호출을 기다리지 않기 때문에 현재 메소드의 실행이 계속됩니다 …”억제 C #에서 비동기 메서드를 안전하게 호출하는 방법”

이것은 “대기없이 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가 제안한 보다 정교한 접근 방식을 사용합니다 .



답변

C # 7에서는 이제 폐기를 사용할 수 있습니다 .

_ = WorkAsync();


답변

경고를 방지하는 확장 방법을 만들 수 있습니다. 확장 메소드는 비어 있거나 예외 처리를 추가 할 수 있습니다 .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 4014Visual 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
}