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


88

그래서 최근에 .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");
    });
}

답변:


115

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

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

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

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


2
마침내 누군가가 정답을 내립니다. @ Travyguy9이 @DrewMarsh 응답을 읽고에 대한 자세한 읽어 보시기 바랍니다TaskContinuationOptions
재스퍼

2
좋은 대답을 찾고있었습니다. "당신 자신의 연속 작업이 예외를 관찰하지 않으면이 전체 워크 플로가 완료되기를 기다리는 사람이이를 관찰하는 사람이 될 것임을 명심하십시오." 그러나 작업이 대기하지 않을 때 기본 대기자는 누구입니까? (이에 대한 답을 찾을 수 없습니다)
티보 D.에게

20

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

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

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

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

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


16

누가 그랬어?

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");
    });

5

보내는 사람 은 MSDNTask.Continuewith

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

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



0

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


예. Wait () 메서드를 피할 수 있습니다. 하지만 결과 작업에서만 작동합니다. 예 : Task <bool>
Alexander Ulmaskulov

실제 질문을 다루지 않기 때문에 반대 투표했습니다. 약간의 가치를 추가하지만 주석이어야합니다.
Sinaesthetic 2017-10-02

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.