为了账号安全,请及时绑定邮箱和手机立即绑定

C#:为什么在任务已经完成的情况下,获取 Task t.Result 需要这么长时间?

C#:为什么在任务已经完成的情况下,获取 Task t.Result 需要这么长时间?

C#
慕村225694 2021-11-28 20:16:16
我想知道为什么从已经完成的任务中获得结果需要这么长时间。List<Task<T>> myTasks = someList.Select(x => Task.Run(() => DoSomethingWith(x)));Task.WaitAll(myTasks.ToArray());var myResults = myTasks.Select(task => task.Result); // the line that takes too long对这些单行进行计时表明,最后一行花费了大量时间(10 个任务超过 25 毫秒)。在我看来,得到结果应该是几乎瞬间的事情,因为结果应该在那个时候已经存在。在这种情况下有没有更好的方法来获得结果?
查看完整描述

2 回答

?
HUH函数

TA贡献1836条经验 获得超4个赞

我会在你更新你的问题时更新这个,但这是我最好的猜测。

这一行不会编译,因为 Select 不返回列表:

List<Task<T>> myTasks = someList.Select(x => Task.Run(() => DoSomethingWith(x)));

我要冒险猜测你实际上正在这样做:

var myTasks = someList.Select(x => Task.Run(() => DoSomethingWith(x)));

...这会产生一个冷IEnumerable:一个只会在它实际被迭代时运行。

在上面的代码中,当您调用它时,您正在对其进行迭代.ToArray()。但是你描述为 25ms 的那条线同样只产生了另一种感冒IEnumerable<>。这里没有做真正的工作:

var myResults = myTasks.Select(task => task.Result);

所以我再次冒险猜测你正在做更多这样的事情:

var myResults = myTasks.Select(task => task.Result).ToList();

...这将重复myTasks 第二次,导致Task.Run(...)为 中的每个项目再次调用someList,然后等待所有这些任务完成。

换句话说,你做了两次工作,其中一次在你最后引用的行中。

幸运的是,有一种更好的方法来完成您正在做的事情,那就是使用任务并行库。

var myResults = someList
    .AsParallel()
    .Select(x => DoSomethingWith(x))
    .ToList();


查看完整回答
反对 回复 2021-11-28
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

如果您确定第 3 行是导致减速的那一行,那么就没什么可做的了。这是所有运行时库代码,MS 在优化方面运行得非常严格。

您可能希望手动迭代 myTasks 以避免 Select 代码,但如果您获得了几毫秒,我会感到惊讶。


查看完整回答
反对 回复 2021-11-28
  • 2 回答
  • 0 关注
  • 253 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信