有async修饰符的异步方法和没有async修饰符的异步方法

4

方法 Add1()Add2() 有什么区别吗?实际上有区别吗?据我所知,使用方法(如 UsageTest() 方法中所示)是相同的。

private async Task<int> Add1(int a, int b)
{
    return await Task.Run(
        () =>
            {
                Thread.Sleep(1000);
                return a + b;
            });
}

private Task<int> Add2(int a, int b)
{
    return Task.Run(
        () =>
            {
                Thread.Sleep(1000);
                return a + b;
            });
}

private async void UsageTest()
{
    int a = await Add1(1, 2);
    int b = await Add2(1, 3);
}
2个回答

6

从语义上来讲,它们几乎是等同的。

主要区别在于 Add1 有更多的开销(对于 async 状态机)。

还有一个小差异; Add1 将会 marshal 回到其原始上下文,而 Add2 不会。如果调用代码不使用 await,这可能会导致死锁:

public void Button1_Click(..)
{
  Add1().Wait(); // deadlocks
  Add2().Wait(); // does not deadlock
}

我在我的博客中详细解释了这种死锁情况,与此同时,在最近的MSDN文章中也有所介绍。

(博客地址) (MSDN文章)


1

Add1会同步运行,直到遇到await关键字。在这种情况下,它没有影响,因为await关键字位于方法的开头。

为了看到这个效果,您可以在Add1和Add2的开头插入Thread.Sleep()方法,并注意标记为async的方法在返回之前会被阻塞。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接