0

이 질문에는 이미 답변이 있습니다.

ContinueWith를 사용하여 메서드를 체인으로 연결하고 해당 메서드에서 비동기 작업을 사용하는 경우 체인 된 메서드가 Task.WhenAll을 완료 할 때 완료를 기다리지 않는 이유는 무엇입니까?

예를 들어 다음 코드

var str1 = "str1";
var str2 = "str2";
var task0 = Task.Run( async ()=> { 
                await Task.Delay(1000);
                return "changed";
            });
var task1 = task0.ContinueWith(async prevTask => {
                await Task.Delay(5000);
                str1 = prevTask.Result;
            });
var task2 = task0.ContinueWith(prevTask => {
                Task.Delay(1000).Wait();
                str2 = prevTask.Result;
            });

await Task.WhenAll(task0, task1, task2);
Console.WriteLine(str1);
Console.WriteLine(str2);

산출물을 산출하다

str1
changed

그러나 비동기 작업으로 다른 작업과 동일한 작업을 시도하지만 Task.Delay에 대한 호출을 차단하면 해당 메서드가 제대로 작동합니다. 예를 들어, 다음과 같이 태스크 3을 추가하십시오.

....
var str3 = "str3";
var task3 = task0.ContinueWith(async prevTask => {
                Task.Delay(2500).Wait();
                str3 = prevTask.Result;
            });

await Task.WhenAll(task0, task1, task2, task3);
Console.WriteLine(str1);
Console.WriteLine(str2);
Console.WriteLine(str3);

다음과 같은 산출물을 산출한다

str1
changed
changed 

디버깅하는 동안, 나는 또한 task1의 상태를 '완결까지'라고 보았는데, 나는 왜 그런지 이해하지 못한다. ContinueWith가 완료되었다고 가정하는 작업을 일으키는 것 같지만 왜 이해가 안되나요?

작동 코드에 대한 링크 :http://rextester.com/WFRTKY13796


  • ContinueWith지원하지 않는다.async따라서 결과 작업은 비동기 대리자의 첫 번째 동기 부분 만 나타냅니다. 전화해야 해.Unwrap(), 만약 당신이 전체적으로 비동기 델리게이트의 완성을 나타내는 작업을 원한다면. - PetSerAl
  • 사용하기에 적절하거나 유용한 경우는 거의 없습니다.ContinueWith. 거의 항상 사용하는 것이 좋습니다.await작업에 대한 지속성을 예약합니다. 사용ContinueWith직접적으로많은올바르게하는 것이 더 어렵습니다. - Servy

1 답변


0

유형task1~이다.Task<Task>결과 집합을 얻기 위해 작업을 기다려야합니다. 이것은 쉽게 추가 할 수 있습니다.await두 번째 예제는 블로킹 호출을 사용하는 반면 수정 된 렉스 스 코드는 다음과 같습니다.

//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Test().Wait();                        
        }

        public static async Task Test(){

            var str1 = "str1_beforeChange";
            var str2 = "str2_beforeChange";
            var str3 = "str3_beforeChange";

            var task0 = Task.Run(async ()=>{
                await Task.Delay(2500);
                return "afterChange";
            });

            //await the async continuation
            var task1 = await task0.ContinueWith(async prevTask => {
                await Task.Delay(5000);
                str1 = prevTask.Result;
            });

            var task2 = task0.ContinueWith(prevTask =>{
                Task.Delay(2500).Wait();
                str2 = prevTask.Result;
            });

            var task3 = task0.ContinueWith(prevTask =>{
                Task.Delay(1000).Wait();
                str3 = prevTask.Result;
            });

            await Task.WhenAll(task0, task1, task2, task3);

            Console.WriteLine(str1);
            Console.WriteLine(str2);
            Console.WriteLine(str3);
        }
    }
}


  • 불필요하게 태스크를 래핑 한 후에 태스크를 래핑하지 않고,불필요하게 작업을 래핑하지 않습니다.그런 다음 포장을 풀지 않아도됩니다. - Servy

연결된 질문


관련된 질문

최근 질문