首页 > 解决方案 > 我可以保证已经运行了可运行的任务延续吗?

问题描述

这是我正在处理的一段代码中显着减少的测试用例:

var i = 0;

var taskCompletionSource = new TaskCompletionSource<object>();
var task = taskCompletionSource.Task;

Task.Run(async () => 
{
    await task;
    i = 1;
});

// Synchronously complete `task`
taskCompletionSource.SetResult(null);

// ???

Console.WriteLine(i);

假设这段代码在async方法的上下文中运行,应该替换什么// ???来确保这段代码打印1而不是0

我相信我理解为什么编写的程序总是会打印0——代码是同步执行的,调度程序没有任何结果。但我很惊讶地得知

await Task.Yield();

还不够。有点讽刺的是(但完全可以理解,因为它不涉及异步执行)

await task;

另一方面,

await Task.Delay(1);

似乎确实足够了,但我不清楚这是保证还是时间上的意外。

以另一种方式问这个问题:我可以编写任何(合理的)代码来保证在继续task之前运行所有的延续吗?

标签: c#async-awaittasktask-parallel-librarytaskcompletionsource

解决方案


我可以保证已经运行了可运行的任务延续吗?

通过awaiting 他们。

var i = 0;

var taskCompletionSource = new TaskCompletionSource<object>();
var task = taskCompletionSource.Task;

var continuation = Task.Run(async () => 
{
    await task;
    i = 1;
});

// Synchronously complete `task`
taskCompletionSource.SetResult(null);

// wait for the continuation
await continuation;

// ouputs 1
Console.WriteLine(i);

如果您使用的是异步方法,那将有效。如果不是,请使其异步。您也可以在技术上阻止(.Wait()而不是await),但这会导致死锁,所以要小心。


推荐阅读