为什么我的TCS没有等待?

时间:2015-09-25 15:30:21

标签: c# .net async-await task-parallel-library taskcompletionsource

async关键字执行会导致CIL发生变化(即使方法中没有等待),但主要是允许await 1}}出席。

但我没想到会发生以下情况:

static void Main(string[] args)
{
    Task t = Go();
    t.Wait();
}

static async Task Go()
{
    Console.WriteLine(1);
    await AAA(3000);
    Console.WriteLine(2);
}


static  Task<object> AAA(int a) // <--- No `async`
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
    return tcs.Task;
}

此印刷品:

1
(wait)
2

但如果我改变

static  Task<object> AAA(int a) 

static async  Task<object> AAA(int a) 

打印:

1
2
(no wait)

问题

为什么我没有看到延迟? TCS仅在三秒后解决。同时,任务没有得到解决,应该等待。

3 个答案:

答案 0 :(得分:8)

如果没有dos_code_id关键字,您将从async返回TaskCompletionSource的任务,等待它完成(这将在延迟完成后发生)。

但是,当您添加AAA关键字时,从该方法返回的任务是状态机的同步完成任务。该任务在其内部(因此)async的任务,但这不是您正在等待的任务。

如果您希望该方法等待TaskCompletionSource的任务,您可以等待TaskCompletionSource的内部任务:

Task<Task>

或等待await ((Task) await AAA(3000)); 而不是返回它:

TaskCompletionSource

甚至更好,等待async Task AAA(int a) { TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); Task.Delay(a).ContinueWith(b => tcs.SetResult(null)); await tcs.Task; } 本身:

Task.Delay

答案 1 :(得分:6)

因为当你从异步方法返回Task时,返回类型为Task<object>,你得到的是Task<Task>与你的任务(你期望等待)。那你应该做的:

static async Task<object> AAA(int a)
{
  await Task.Delay(a);
  return null;
}

简而言之,尽量避免在一种方法中混合async-await和直接任务操作。

答案 2 :(得分:2)

正如Serg所提到的,请在Visual Studio中查看此示例:

        static async Task<int> AAA(int a) // <--- No `async`
        {
             TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
             Task.Delay(a).ContinueWith(b =>
             {
                  tcs.SetResult(1);
             });
             return tcs.Task;
        }

你会收到这样的错误:

由于这是一个异步方法,因此返回表达式的类型必须为&#39; int&#39;而不是&#39;任务&#39; ,因为您的方法将同步运行。这就是为什么需要返回int,而不是Task