【问题标题】:C# awaitable problemsC# 等待问题
【发布时间】:2015-12-03 09:21:07
【问题描述】:

documents 是一个IDictionary<string, string>,其中参数是<filename, fileUrl>

DocumentHandler.Download() 返回一个Task<Memorystram>

此代码有效:

foreach (var x in documents.Keys)
    {
        var result = await DocumentHandler.Download(new Uri(documents[x]));
        // other code
    }

但是它是同步运行的。

为了异步运行,我写了这段代码:

var keys =
documents.Keys.Select(async x =>
    {
        return Tuple.Create(x, await DocumentHandler.Download(new Uri(documents[x])));
    });
await Task.WhenAll(keys);
foreach (var item in keys)
{
    var tpl = item.Result;
    // other code
}

它不起作用,它崩溃了,最后一行没有显示异常var tpl = item.Result;为什么?

【问题讨论】:

    标签: c# exception asynchronous async-await


    【解决方案1】:

    您的keys 变量将在您每次评估它时创建一个 任务集...所以在等待第一组任务完成后,您将迭代一个新集的未完成任务。解决此问题的简单方法是添加对ToList() 的调用:

    var keys = documents
        .Keys
        .Select(async x => Tuple.Create(x, await DocumentHandler.Download(new Uri(documents[x]))))
        .ToList();
    await Task.WhenAll(keys);
    foreach (var item in keys)
    {
        var tpl = item.Result;
        // other code
    }
    

    【讨论】:

    • 正确,但也注意到元组没有 Result 属性;)所以 OP 意味着编译时错误 var tpl = item.Result;。我也认为keysList<Tuple<string,Task<Memorystram>>> 的类型,所以你也不能等待它们。
    • @M.kazemAkhgary:OP 没有尝试使用TupleResult 属性-他们正在使用Task<Tuple<string, ...>>Result 属性。异步 lambda 表达式将创建一个 Func<Task<...>>。如果 OP 遇到编译时错误,他们不会说它“在没有显示异常的情况下崩溃”。
    • @M.kazemAkhgary:还要注意它不是Tuple<string, Task<MemoryStream>>,因为异步 lambda 表达式正在等待 DocumentHandler.Download 的结果。
    • @Emaborsa:你明白 LINQ 是懒惰的吗?每次您在代码中迭代 keys 变量时,您都在创建新任务?如果没有,你真的应该重新审视 LINQ 和延迟执行的基础知识。
    • 哦。我得到了它。感谢您的解释。对不起! ;)
    猜你喜欢
    • 2011-11-11
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2021-05-24
    • 2021-10-11
    • 2014-10-27
    相关资源
    最近更新 更多