await 和 myTask.Result 之间的区别

问题描述 投票:0回答:1

当您调用异步方法时,它会返回一个

Task<T>
,其中
T
是结果的类型。

现在,您有两种方法来处理此任务。您可以使用 getter

.Result
等待任务完成并获取包装的值,也可以使用
await
,看起来它在做同样的事情。或者不是吗?

我试图找到这个问题的答案,并看到@Frank Fajardo 回复这样说:

await 异步解开任务结果 [...] 结果会阻塞 [...]

我不太确定@Frank Fajardo 在说什么。

await
不也阻止了
Main()
的执行吗?

这是一个示例:请注意,

foo()
仅在barAsync()返回的任务完成后(当使用
await barAsync()
时)被调用。

fooTask().Result

barAsync().Result
也是如此:
using System;
using System.Threading;
using System.Threading.Tasks;

public class App
{
    public static async Task Main(string[] args)
    {
        Console.WriteLine (await barAsync());
        Console.WriteLine (foo());
        
        Console.WriteLine (fooTask().Result);
        Console.WriteLine (foo());
        
        Console.WriteLine (barAsync().Result);
        Console.WriteLine (foo());
    }
    
    public static Task<string> fooTask()
    {
        return Task.Run(() => {
           Thread.Sleep(1000);
           return "faz";
        });
    }
    
    public static async Task<string> barAsync()
    {
       Thread.Sleep(5000);
       return "baz";
    }
    
    public static string foo()
    {
       return "--- faz ---";
    }
}

那么,有什么区别呢?使用 
await

时哪个线程不会被阻塞?

    

c# asynchronous async-await task
1个回答
0
投票
.Wait()

会阻塞当前线程,直到任务完成。

await
不会阻塞当前线程。相反,当前执行流程(
async
方法)被挂起,当任务完成时,流程将在完成任务的线程上恢复。在大多数情况下,完成线程是
ThreadPool
线程。完成线程是由异步方法的内部实现选择的。
某些应用程序类型,例如 WinForms 和 WPF 应用程序,在主线程上配备了特定于应用程序的 

SynchronizationContext

,它通过重新安排 
await 延续来改变每个
await
的行为,通常将其重定向回UI 线程。
控制台应用程序没有配备 

SynchronizationContext

(并且不存在专门的内置实现)。由于主线程的终止会导致进程的终止,因此具有 async

Main
 方法的控制台应用程序实际上会阻塞主线程,以防止进程终止。阻塞是通过 
.GetAwaiter().GetResult()
执行的,这与
.Wait
类似,只是异常传播方式不同。
    

© www.soinside.com 2019 - 2024. All rights reserved.