【发布时间】:2019-04-07 03:29:53
【问题描述】:
这是我正在处理的一段代码中显着减少的测试用例:
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 的所有延续都在继续之前运行吗?
【问题讨论】:
-
编写的代码不起作用,因为您没有等待从 Task.Run(...) 创建的任务。你完成了
task,但Console.WriteLine(i)在i = 1之前被执行。但我不确定你要做什么。见fiddler -
await Task.Delay(1);起作用的原因可能是因为它强制线程移位,因此任务将在Console.Writeline之前执行。 -
顺便说一句。这是一个糟糕的使用模式。如果内部方法的主体返回一些数据,则应使用
return i;代替。在这种情况下,初始化将在内部主体中完成。这个概念称为 ENCAPULATION,是 OOP 的四大支柱之一。 -
关闭
i只是为了说明问题的一个例子,但谢谢。
标签: c# async-await task task-parallel-library taskcompletionsource