为什么我的TCS没有等待?

Roy*_*mir 9 .net c# task-parallel-library async-await taskcompletionsource

async关键字导致CIL改变(即使有方法内部没有的await),但它主要是允许await存在.

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

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;
}
Run Code Online (Sandbox Code Playgroud)

这个印刷品:

1
(wait)
2
Run Code Online (Sandbox Code Playgroud)

但如果我改变

static  Task<object> AAA(int a) 
Run Code Online (Sandbox Code Playgroud)

static async  Task<object> AAA(int a) 
Run Code Online (Sandbox Code Playgroud)

它打印:

1
2
(no wait)
Run Code Online (Sandbox Code Playgroud)

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

i3a*_*non 8

如果没有async关键字,您将返回TaskCompletionSource任务AAA,因此等待它完成(这将在延迟完成后发生).

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

如果您希望该方法等待TaskCompletionSource任务,您可以等待以下内部任务Task<Task>:

await ((Task) await AAA(3000));
Run Code Online (Sandbox Code Playgroud)

或等待TaskCompletionSource而不是返回它:

async Task AAA(int a)
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
    Task.Delay(a).ContinueWith(b => tcs.SetResult(null));
    await tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,等待Task.Delay自己:

async Task<object> AAA(int a)
{
    await Task.Delay(a);
    return null;
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*sev 6

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

static async Task<object> AAA(int a)
{
  await Task.Delay(a);
  return null;
}
Run Code Online (Sandbox Code Playgroud)

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