Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Task.Wait()在Console.WriteLine()-.NET Core中的行为不符合预期?_.net_Asynchronous_Concurrency_Task Parallel Library_.net Core - Fatal编程技术网

为什么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任务停止,以防止后台任务终止。So
Console.Read()
阻塞UI线程,如果在质数任务完成之前我没有按任何键,控制台中的输出将正确
216816
。在这里之前都没问题

所以我认为调用
Wait()
将具有与主UI任务阻塞并等待质数任务完成相同的效果(至少如果在
OnCompleted
回调之前调用)。这种情况确实会发生,但在这两种情况下(选项1和选项2),主线程都会等待,然后终止,没有任何输出

为什么呢?我对这种行为的期望如下(可能有点偏离,因此我的问题是)

  • 主UI线程等待/阻止任务完成,订阅已完成的任务,因此立即执行回调,输出打印为
    216816
    。但事实并非如此

  • 主UI线程等待/阻塞,当任务完成时,它会在执行
    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().OnCompleted()
    之前退出。这符合我对选项2的期望,但是选项1呢?