当你等待同步方法时会发生什么?

9
如果我有一个同步的方法 "GetStrings()":
private static Task<string[]> GetStrings(IEnumerable<int> ids)
{
    var tasks = ids.Distinct().Select(GetString);
    return Task.WhenAll(tasks);
}

private static async Task<string> GetString(int stringId)
{
    await Task.Delay(15000);
    return "hello" + stringId;
}

“我自己调用了异步方法“GetString()”,它本身也会调用这个方法。同时,我从一个异步方法中调用了这个同步方法“GetStrings()”。”
public static async Task Main()
{
    var ids = new List<int> { 1, 2, 3 };
    await GetStrings(ids);
    Console.WriteLine("all done");
    Console.ReadLine();
}

如果GetStrings()实际上是异步的(并在Task.WhenAll上执行等待),那么行为会有什么不同?它是否只是阻止Task.WhenAll阻塞线程?我找到了一些类似于这样的生产代码,因此我编写了这个小例子来尝试理解发生了什么。但很难确定其中的差异。

看起来是这个的重复:https://dev59.com/GmIk5IYBdhLWcg3wn_j1 - Evk
1
这是一个好问题。我想知道为什么有人标记它。 - Donald Duck
1个回答

10

Task.WhenAll不会像Task.WaitAll一样阻塞,它只是返回一个任务,在所有原始任务都完成后就完成了。

重要的是要理解,你不是等待一个方法 - 你等待一个(或某个可等待的类型)。等待机制不关心你如何获得该值。

如果GetStrings是异步的,则有一个重要的区别:任何抛出的异常(例如如果ids为null)将导致一个故障的任务,而当前情况下异常将直接被抛出。


所以我猜最好用async await来包装它,对吧? - Ehsan Sajjad
1
@EhsanSajjad:不一定。我不会毫无思考地这样做。如果异常的唯一原因是存在错误,尽早发现它是有用的。 - Jon Skeet

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