28

나는 C #의 async / await / continuewith로 조금 놀려고한다. 내 목표는 병렬로 실행되는 2 개의 작업을해야한다는 것입니다.하지만 어떤 작업이 순서대로 작업 순서를 실행하고 있습니다. 그렇게하기 위해 나는List<Task>병렬로 실행되는 2 개 이상의 작업을 나타내는ContinueWith각각의Task내 문제는 계속 콜백이 실행되지 않는 것 같습니다.await taskList이미 반환되었습니다.

요약하기 위해, 여기에 내가 기대하고있는 것을 설명하는 샘플이 있습니다.

class Program
{
    static public async Task Test()
    {
        System.Console.WriteLine("Enter Test");
        await Task.Delay(100);
        System.Console.WriteLine("Leave Test");
    }

    static void Main(string[] args)
    {
        Test().ContinueWith(
        async (task) =>
        {
            System.Console.WriteLine("Enter callback");
            await Task.Delay(1000);
            System.Console.WriteLine("Leave callback");
        },
        TaskContinuationOptions.AttachedToParent).Wait();
        Console.WriteLine("Done with test");
    }
}

예상되는 출력은

Enter Test
Leave Test
Enter callback
Leave callback
Done with test

그러나 출력은 다음과 같습니다.

Enter Test
Leave Test
Enter callback
Done with test

작업을 수행 할 수있는 방법이 있습니까?ContinueWith완성 된 것으로 간주되기 전에 제공된 함수가 완료 될 때까지 기다리는 것입니까? 즉. .Wait는 두 작업이 모두 완료 될 때까지 기다릴 것이며, 원래 작업은 ContinueWith에 의해 반환됩니다.


  • 그 (것)들을 제거하는 것을 시도하십시오await...에서await Task.Delay(1000); - Alessandro D'Andria
  • 사실 그것이 효과가있었습니다. 내가 기다리는 것을 제거하고, 비동기는 아무것도 기다리지 않기 때문에 제거합니다. 그러나 나는 그것이 작동하는 이유를 놓치고 있습니다. 이론적 설명이 있습니까? - chouquette
  • " 콜백 남기기 " " 테스트 완료 " 뒤에 표시됩니다. - Francesco De Lisi
  • 부름task.ContinueWith(async (task) => { .. })실제로 < Task > 작업을 반환합니다.이리. 이것이 바로 당신이 찾고있는 것입니까? - noseratio
  • 래핑 된 작업은 필요하지 않은 경우 사용하지 않는 것이 좋습니다.여기에 있습니다.내 말은. - noseratio

3 답변


35

여러 작업을 연결하는 경우ContinueWith메서드를 사용하면 반환 유형이Task<T>이므로T전달 된 대리자 / 메서드의 반환 형식입니다.ContinueWith.

비동기 대의원의 반환 유형은Task, 당신은 결국Task<Task>비동기 대의원이 당신을 돌려 줄 때까지 기다리는 것입니다.Task첫 번째 이후에 수행됩니다.await.

이 문제를 해결하려면 반환 된 값을 사용해야합니다.Task, 당신의Task<Task>. 사용Unwrap확장 방법을 추출합니다.


24

네가하고있을 때.async프로그래밍, 당신은ContinueWithawait, 같은 :

class Program
{
  static public async Task Test()
  {
    System.Console.WriteLine("Enter Test");
    await Task.Delay(100);
    System.Console.WriteLine("Leave Test");
  }

  static async Task MainAsync()
  {
    await Test();
    System.Console.WriteLine("Enter callback");
    await Task.Delay(1000);
    System.Console.WriteLine("Leave callback");
  }

  static void Main(string[] args)
  {
    MainAsync().Wait();
    Console.WriteLine("Done with test");
  }
}

사용하는 코드await훨씬 더 깔끔하고 유지하기 쉽습니다.

또한 다음과 함께 부모 / 자식 작업을 사용하지 않아야합니다.async작업 (예 :AttachedToParent). 그들은 함께 일하도록 설계되지 않았습니다.


5

나는 이미 받아 들여진 답을 보완하기 위해 나의 대답을 추가하고 싶다. 수행하려는 작업에 따라 종종 비동기 대의원 및 래핑 된 작업이 복잡 해지는 것을 피할 수 있습니다. 예를 들어, 다음과 같이 코드를 다시 고려할 수 있습니다.

class Program
{
    static async Task Test1()
    {
        System.Console.WriteLine("Enter Test");
        await Task.Delay(100);
        System.Console.WriteLine("Leave Test");
    }

    static async Task Test2()
    {
        System.Console.WriteLine("Enter callback");
        await Task.Delay(1000);
        System.Console.WriteLine("Leave callback");
    }

    static async Task Test()
    {
        await Test1(); // could do .ConfigureAwait(false) if continuation context doesn't matter
        await Test2();
    }

    static void Main(string[] args)
    {
        Test().Wait();
        Console.WriteLine("Done with test");
    }
}

연결된 질문


관련된 질문

최근 질문