[c#] PrevTask.Wait ()는 ContinueWith (태스크 라이브러리에서)와 함께 사용하는 것이 좋습니다.

그래서 최근에 .ContinueWith for Tasks를 사용하는 방법이 적절한 사용 방법이 아니라는 말을 들었습니다. 나는 아직 인터넷에서 이것에 대한 증거를 찾지 못했기 때문에 여러분들에게 물어보고 답이 무엇인지 볼 것입니다. 다음은 .ContinueWith를 사용하는 방법의 예입니다.

public Task DoSomething()
{
    return Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Step 1");
    })
    .ContinueWith((prevTask) =>
    {
        Console.WriteLine("Step 2");
    })
    .ContinueWith((prevTask) =>
    {
        Console.WriteLine("Step 3");
    });
}

이제 저는 이것이 간단한 예이며 매우 빠르게 실행된다는 것을 알고 있지만 각 작업이 더 긴 작업을 수행한다고 가정합니다. 그래서 제가들은 것은 .ContinueWith에서 prevTask.Wait (); 그렇지 않으면 이전 작업이 완료되기 전에 작업을 수행 할 수 있습니다. 그게 가능할까요? 두 번째 및 세 번째 작업은 이전 작업이 완료된 후에 만 ​​실행될 것이라고 가정했습니다.

코드 작성 방법을 들었습니다.

public Task DoSomething()
{
    return Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Step 1");
    })
    .ContinueWith((prevTask) =>
    {
        prevTask.Wait();
        Console.WriteLine("Step 2");
    })
    .ContinueWith((prevTask) =>
    {
        prevTask.Wait();
        Console.WriteLine("Step 3");
    });
}



답변

Ehhh …. 현재 답변 중 일부가 누락 된 것 같습니다. 예외가 발생하면 어떻게됩니까?

Wait연속을 호출하는 유일한 이유 는 연속 자체의 선행 항목에서 잠재적 인 예외를 관찰하는 것입니다. Resulta의 경우 액세스 한 경우 Task<T>Exception속성에 수동으로 액세스 한 경우에도 동일한 관찰이 발생합니다 . 솔직히, 예외가 있으면 불필요한 오버 헤드가 발생하는 리 레이즈 대가를 지불 WaitResult것이기 때문에 저는 전화 하거나 액세스 하지 않을 것입니다. 대신 당신은 단지 IsFaulted선행 에서 속성을 확인할 수 있습니다 Task. 또한 만에 하나 성공 또는 실패에 따라 졌지 여러 형제 연속 요청에 체인에 의해 갈래의 워크 플로우를 만들 수 있습니다 TaskContinuationOptions.OnlyOnRanToCompletionTaskContinuationOptions.OnlyOnFaulted.

이제 계속되는 선행 항목의 예외를 관찰 할 필요는 없지만 “1 단계”가 실패한 경우 워크 플로가 진행되는 것을 원하지 않을 수 있습니다. 이 경우 : 지정하는 TaskContinuationOptions.NotOnFaulted당신에게 ContinueWith전화하는 것은 이제까지도 발사에서 연속 논리를 방지합니다.

자신의 연속 작업이 예외를 관찰하지 못하는 경우이 전체 워크 플로가 완료되기를 기다리는 사람이이를 관찰 할 수 있습니다. 어느 그들이있어 Wait온 보내고 Task상류하거나 완료되면 알고 자신의 계속에 압정으로 고정했다. 후자의 경우, 이들의 연속은 앞서 언급 한 관찰 논리를 사용해야합니다.


답변

올바르게 사용하고 있습니다.

대상 Task가 완료 될 때 비동기 적으로 실행되는 연속을 만듭니다 .

출처 : Task.ContinueWith 메서드 (Action as MSDN)

전화를 갖는 prevTask.Wait()모든에 Task.ContinueWith즉, 실제로 코드의 특정 비트가 무엇을하는지 이해하지 않기 때문에 “슈퍼 확인아요”로 뭔가를하고 – 호출하는 것은 불필요한 로직을 반복하는 이상한 방법처럼 보인다. ArgumentNullException어쨌든 던져졌을 곳 을 던지기 위해 null을 확인하는 것과 같습니다 .

그래서, 누가 당신에게 틀렸다고 말했고 아마도 왜 Task.ContinueWith존재 하는지 이해하지 못할 것 입니다.


답변

누가 그랬어?

MSDN 인용 :

대상 Task가 완료 될 때 비동기 적으로 실행되는 연속을 만듭니다.

또한 이전 작업이 완료되기를 기다리지 않는 경우 계속 작업 의 목적은 무엇입니까?

직접 테스트 할 수도 있습니다.

Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Step 1");
        Thread.Sleep(2000);
    })
    .ContinueWith((prevTask) =>
    {
        Console.WriteLine("I waited step 1 to be completed!");
    })
    .ContinueWith((prevTask) =>
    {
        Console.WriteLine("Step 3");
    });


답변

보내는 사람 은 MSDNTask.Continuewith

반환 된 Task는 현재 작업이 완료 될 때까지 실행되도록 예약되지 않습니다. continuationOptions 매개 변수를 통해 지정된 기준이 충족되지 않으면 연속 작업이 예약되지 않고 취소됩니다.

첫 번째 예에서 예상하는 방식이 올바른 방식이라고 생각합니다.


답변

Task.Factory.StartNew 대신 Task.Run 사용을 고려할 수도 있습니다.

Stephen Cleary의 블로그 게시물그가 참조 하는 Stephen Toub의 게시물 은 차이점을 설명합니다. 이 답변 에는 토론도 있습니다 .


답변

액세스 Task.Result하면 실제로 다음과 유사한 논리를 수행합니다.task.wait


답변

나는 이미 말한 많은 것을 반복 할 prevTask.Wait() 필요가 없습니다 .

더 많은 예제를 보려면 Continuation Tasks를 사용하여 Chaining Tasks 로 이동 하고 좋은 예제가있는 Microsoft의 또 다른 링크를 참조하십시오.