为什么Task.Wait()在Console.WriteLine()-.NET Core中的行为不符合预期?
我试图更好地理解异步编程的基础知识,因此我创建了以下代码段:为什么Task.Wait()在Console.WriteLine()-.NET Core中的行为不符合预期?,.net,asynchronous,concurrency,task-parallel-library,.net-core,.net,Asynchronous,Concurrency,Task Parallel Library,.net Core,我试图更好地理解异步编程的基础知识,因此我创建了以下代码段: private void TaskContinuations() { // Task for counting prime numbers Task<int> primeNumberTask = Task.Run(() => Enumerable.Range(2, 3000000) .Count(n => Enumerable.Range(
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
}
private void TaskContinuations()
{
//计算素数的任务
任务primeNumberTask=Task.Run(()=>
可枚举范围(2300000)
.Count(n=>
可枚举范围(2,(int)数学Sqrt(n)-1)
。全部(i=>n%i>0));
var awaiter=primeNumberTask.GetAwaiter();
//primeNumberTask.Wait();//选项1:正在等待但不打印(此处非常意外)
等待者。未完成(()=>
{
var result=waiter.GetResult();
控制台写入线(结果);
});
//primeNumberTask.Wait();//选项2:正在等待但不打印(这里有点像预期的那样)
Console.Read();//选项3:按预期工作和打印
}
我知道我必须阻止主UI任务停止,以防止后台任务终止。SoConsole.Read()
阻塞UI线程,如果在质数任务完成之前我没有按任何键,控制台中的输出将正确216816
。在这里之前都没问题
所以我认为调用Wait()
将具有与主UI任务阻塞并等待质数任务完成相同的效果(至少如果在OnCompleted
回调之前调用)。这种情况确实会发生,但在这两种情况下(选项1和选项2),主线程都会等待,然后终止,没有任何输出
为什么呢?我对这种行为的期望如下(可能有点偏离,因此我的问题是)
216816
。但事实并非如此李>
或
OnCompleted
之前立即执行。所以这里没有预期的输出OnCompleted
方法,因为
此API支持产品基础架构,不打算从代码中直接使用
第二件事是在任务完成后调用OnCompleted
方法。因此,这里有一个竞争条件-任务完成后,.Net
尝试在它之后执行该方法,但代码中没有任何内容等待等待者
,因此程序在打印任何内容之前退出
在这种情况下,您应该使用的代码是,等待第二个任务:
private void TaskContinuations()
{
// Task for counting prime numbers
var primeNumberTask = Task.Run(() =>
Enumerable.Range(2, 3000000)
.Count(n =>
Enumerable.Range(2, (int)Math.Sqrt(n) - 1)
.All(i => n % i > 0)));
// continuation
var awaiterTask = primeNumberTask.ContinueWith(t =>
{
var result = t.Result;
Console.WriteLine(result);
});
// wait for everything to execute
awaiterTask.Wait();
}
请注意,这一点,并应谨慎使用。可以找到另一篇关于延续技术的文章。您还有
Console.Read()吗代码>当您取消注释primeNumberTask.Wait()时代码>。如果没有-程序在有机会输出任何内容时已返回。如果我保留Console.Read(),则不会返回;它在所有情况下都会打印“216816”。给出的选项为“独占或”;-)@如果您没有Console.Read()在选项2中,程序在触发.OnCompleted()
之前退出。这符合我对选项2的期望,但是选项1呢?