我想更好地了解异步编程的基础知识,因此我创建了以下代码片段:
private void TaskContinuations()
{
// Task for counting prime numbers
Task<int> primeNumberTask = Task.Run(() =>
Enumerable.Range(2, 3000000)
.Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1)
.All(i => n % i > 0)));
var awaiter = primeNumberTask.GetAwaiter();
// primeNumberTask.Wait(); // Option 1: Waiting but not printing (rather unexpected here)
awaiter.OnCompleted(() =>
{
var result = awaiter.GetResult();
Console.WriteLine(result);
});
//primeNumberTask.Wait(); // Option 2: Waiting but not printing (kind of expected here)
Console.Read(); // Option 3: Works and prints as expected
}
我知道我需要防止主UI任务停止以避免终止后台任务。因此,
Console.Read();
会阻塞UI线程,并且如果在质数任务完成之前没有按键,则控制台中的输出将正确显示216816
。到这里都很清楚。因此,我认为调用
Wait();
会产生相同的效果(至少在OnCompleted
回调之前调用),即主UI任务会阻塞并等待质数任务完成。确实会发生这种情况,但无论是选项1还是选项2,主线程都会等待然后终止而没有任何输出。为什么会这样? 我的预期行为如下(可能有些偏差,因此我的问题)
- 主UI线程等待/阻塞任务直到它完成,订阅已完成的任务,因此立即执行回调,输出打印为
216816
。 但这并没有发生!
- 主UI线程等待/阻塞,当任务完成时,在执行
OnCompleted
之前立即完成。因此,这种情况下不会产生任何输出。
Console.Read();
,程序会在.OnCompleted()
被触发之前退出。 - zerkmsOnCompleted
回调被安排在另一个线程中运行。 - zerkms