将任务字典转换为结果字典

2023-11-24

我有一个程序必须处理多个对象并进行分析。每个分析结果都会生成一个字符串,并将这些字符串连接起来以创建报告。该报告需要按一定顺序排列结果,但我想异步分析每个项目,因此我通过将所有内容放入字典中来管理它,然后我可以在准备最终输出之前对其进行排序。

注意:为了这个示例,我将假装我们正在分析当前程序集的类型,尽管在我的例子中它比这更复杂。

这样做的基本模式(我认为)是这样的:

var types = myAssembly.GetTypes();
var tasks = types.ToDictionary( key => key, value => AnalyzeType(value) );
//AnalyzeType() is an async method that returns Task<string>.

现在我们有了一个热门任务的字典,在创建字典时,这些任务可能已完成,也可能尚未完成,因为我没有等待任何东西。

现在就可以得到结果了。我该怎么做?

Await

理论上我所要做的就是等待每项任务; wait 操作的结果是值本身。但这不会转换任何东西。

var results = tasks.ToDictionary( k => k.key, async v => await v.Value );
Console.WriteLine(results.GetType().FullName);

Output:

System.Collections.Generic.Dictionary'2[[System.Type, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Threading.Tasks.Task'1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

我很困惑...我想通过把await在Task前面,c#会将其转换为结果。但我还有一本任务字典。

获取结果()

另一种方法是使用这个:

var results = tasks.ToDictionary( key => key, value => value.GetAwaiter().GetResult() );
Console.WriteLine(results.GetType().FullName);

Output:

System.Collections.Generic.Dictionary'2[[System.Type, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

所以这似乎得到了我想要的,但我不得不删除await关键字,现在我从编译器收到警告,该方法将同步执行。

我可以添加

await Task.WhenAll(tasks.Select( kvp => kvp.Value));

...放弃控制权,直到所有任务完成运行(因为可能需要一段时间),所以我的整体解决方案是:

await Task.WhenAll(tasks.Select( kvp => kvp.Value));
var results = tasks.ToDictionary( key => key, value => value.GetAwaiter().GetResult() );
Console.WriteLine(results.GetType().FullName);

我想这有效。但似乎这不是正确的方法;我对打电话表示怀疑GetAwaiter().GetResult(),我宁愿不做额外的事情WhenAll()如果不需要,也不应该这样做,因为我正在单独获取每项任务的等待者和结果。

这样做的正确方法是什么?为什么没有await关键字在我的第一个示例中起作用吗?我需要吗GetResult()?如果我这样做,包括在内是个好主意吗?await Task.WhenAll(),还是简单地依赖于GetAwaiter()调用(无论如何都会稍后发生)?

单击此处获取小提琴如果你想使用它。

编辑(答案):

感谢肖恩的正确答案。如果有人想要一些东西,他们可以将其放入他们的代码库中,这是一个通用的扩展方法。

public static async Task<Dictionary<TKey, TResult>> ToResults<TKey,TResult>(this IEnumerable<KeyValuePair<TKey, Task<TResult>>> input)
{
    var pairs = await Task.WhenAll
    (
        input.Select
        ( 
            async pair => new { Key = pair.Key, Value = await pair.Value }
        )
    );
    return pairs.ToDictionary(pair => pair.Key, pair => pair.Value);
}

为什么await 关键字在我的第一个示例中不起作用?

The await关键字解开Task<T>在一个背景下async方法,对类型的基础结果进行操作<T>,并包裹async方法的返回值返回到Task。这就是为什么每个async方法/函数返回其中之一void, Task, or Task<T>(注意void仅适用于事件)。一个async方法不返回未包装的值;我们从未见过像这样的方法签名public async int SomeMethod(),因为返回int不会编译成async方法。它需要返回一个Task<int>反而。

这样做的正确方法是什么?

这是一种方法(用小提琴) 转换具有 type 值的字典Task<T>到具有 type 值的字典<T>:

using System.Threading.Tasks; 
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public async static void Main()
    {
        // create a dictionary of 10 tasks
        var tasks = Enumerable.Range(0, 10)
            .ToDictionary(i => i, i => Task.FromResult(i * i));

        // await all their results
        // mapping to a collection of KeyValuePairs
        var pairs = await Task.WhenAll(
            tasks.Select(
                async pair => 
                    new KeyValuePair<int, int>(pair.Key, await pair.Value)));

        var dictionary = pairs.ToDictionary(p => p.Key);

        System.Console.WriteLine(dictionary[2].Value); // 4
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将任务字典转换为结果字典 的相关文章

  • 使用 POST 的 HttpWebRequest 的性能

    我有一个用于测试网络服务的小工具 它可以使用 POST 或 GET 调用 Web 服务 使用POST的代码是 public void PerformRequest WebRequest webRequest WebRequest Creat
  • 如何使用T4从一个模板同时生成两个文件?

    我遇到的情况是 我需要生成两个 CSharp 代码文件 它们的代码几乎相同 但方法的输入和输出类型的命名空间不同 事实上 每个文件都针对特定国家 地区 并且类型来自特定国家 地区的 WSDL 我正在围绕服务编写一些包装器 逻辑完全相同 但从
  • CMake(Ninja 后端)使用 /MT 编译

    我有一个类似的问题CMake 使用 MT 而不是 MD 进行编译 https stackoverflow com questions 14172856 cmake compile with mt instead of md但有一些差异 我正
  • 我担心我添加了太多接口

    我正在构建我的领域模型并继续重构它 正如我所做的那样 我发现我喜欢接口 因为它允许我根据接口为具体类型创建可重用的方法 控制器 视图 但是 我发现每次向域实体之一添加新属性时 我都会创建一个接口 例如 我有一个会员状态从抽象继承的对象Ent
  • 在 C# 中解析 JS Date.toIsoString

    我需要将 JS 日期存储为 ISO 8601 日期 我目前正在从格式为 2019 06 22T00 00 00 000Z 的表单中获取日期 正如 JS 的 toIsoString 方法所期望的那样 当这个日期传递到我的 API 控制器时 我
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 当我尝试传递临时地址作为参数时,它是一个 UB 吗?

    对于以下 C 代码 include
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • 运行实体框架自定义工具,它有什么作用?

    在 Visual Studio 中 当使用实体框架并为 tt 和 Context tt 文件应用运行自定义工具时 它是什么以及它有什么作用 为什么它解决数据库同步问题 有时 为什么我应该在运行 tt 之前运行它 Context tt 它被称
  • 在 Visual Studio 2012 Express 中设置 C++ 调试环境

    我需要调试的应用程序需要设置环境变量 这在 Visual Studio 2012 中似乎非常复杂 我想做类似的事情 set path c foo c bar c windows c program files application set
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • Windows Phone 的 JSON 反序列化

    我正在尝试反序列化以下 JSON 但我真的不知道如何使用 JSON net 来完成这项工作 我正在使用 C 和 JSON Net 库 我的 JSON 如下 found 3 bounds 43 54919 172 62148 43 54487
  • 查找数组中的多个索引

    假设我有一个像这样的数组 string fruits watermelon apple apple kiwi pear banana 是否有一个内置函数可以让我查询 apple 的所有索引 例如 fruits FindAllIndex ap
  • 如何防止 Lotus Notes 用户转发或复制通过 System.Net.Mail 发送的邮件?

    我想使用 SMTP 客户端 uiing microsft net 以 C 作为编程语言发送电子邮件 但是对于通过SMTP客户端发送的电子邮件 我们是否可以添加 禁止转发 或 禁止复制 等安全功能 我不希望电子邮件的收件人转发或复制电子邮件的
  • 为什么存在系统调用

    我一直在阅读有关系统调用及其在 Linux 中如何工作的内容 我还有更多的阅读要做 但我读过的一件事都没有回答 那就是 为什么我们需要系统调用 我知道系统调用是用户空间程序要求内核执行某些操作的请求 但我的问题基本上是 为什么用户空间程序本
  • java有类似C#的属性吗? [复制]

    这个问题在这里已经有答案了 C 属性 我的意思是 get 和 set 方法 是一个非常有用的功能 java 也有类似 C 的属性吗 我的意思是我们如何在 java 中实现类似以下 C 代码的内容 public string Name get
  • 稀疏矩阵超定线性方程组c/c++库

    我需要一个库来解决 Ax b 系统 其中 A 是一个非对称稀疏矩阵 每行有 8 个条目 而且可能很大 我认为实现双共轭梯度的库应该没问题 但我找不到一个有效的库 我尝试过 iml 但 iml sparselib 包中缺少一些标头 有小费吗
  • 使用空的weak_ptr作为参数调用map::count安全吗?

    打电话安全吗map count http www cplusplus com reference map map count on an 未初始化因此为空weak ptr http en cppreference com w cpp mem
  • 将同步 zip 操作转换为异步

    我们有一个现有的库 其中一些方法需要转换为异步方法 但是我不确定如何使用以下方法执行此操作 错误处理已被删除 该方法的目的是压缩文件并将其保存到磁盘 请注意 zip 类不公开任何异步方法 public static bool ZipAndS

随机推荐