【发布时间】:2017-04-23 08:21:30
【问题描述】:
我试图更好地理解异步编程的基础知识,所以我创建了以下 sn-p:
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(); 会产生与主 UI 任务阻塞并等待质数任务完成相同的效果(至少如果在 OnCompleted 回调之前调用)。这确实发生了,但在这两种情况下(选项 1 和选项 2),主线程都会等待,然后终止而没有任何输出。
这是为什么呢?我对行为的期望如下(可能有点偏离,因此是我的问题)
- 主 UI 线程等待/阻塞任务直到它完成,订阅完成的任务,所以回调立即执行,输出打印为
216816。但这不会发生!
或
- 主 UI 线程等待/阻塞,当任务完成时,它会在执行
OnCompleted之前立即执行此操作。所以这里没有预期的输出。
那么我在这里错过了什么,有人可以解释一下我吗?
【问题讨论】:
-
当您取消注释
primeNumberTask.Wait();时,您是否还有Console.Read();。如果你不这样做 - 程序在它有机会输出任何东西的那一刻就已经返回了。 -
不保留 Console.Read();它在所有情况下都会打印“216816”。给出的选项是“独占或”;-)
-
@anytoe 如果选项 2 中没有
Console.Read();,则程序会在触发.OnCompleted()之前退出。 -
这符合我对选项 2 的期望,但选项 1 呢?
标签: .net asynchronous concurrency task-parallel-library .net-core