C#:为什么任务完成后要花很长时间才能获得任务t.Re​​sult? [英] C#: Why does it take so long to get a Task t.Result when the task has already finished?

查看:53
本文介绍了C#:为什么任务完成后要花很长时间才能获得任务t.Re​​sult?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么花这么长时间才能从已经完成的任务中获得结果.

I'm wondering why it takes so long to get results from already finished tasks.

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毫秒).在我看来,获取结果应该几乎是瞬时的,因为当时结果应该已经存在.在这种情况下是否有更好的方法来获得结果?

Timing these individual lines shows that a significant amount of time is spent in the last line (more than 25ms for 10 tasks). In my mind, getting the result should be something that is almost instantaneous as the result should already exist at that time. Is there a better way to get the results in this kind of situation?

推荐答案

我将在您更新问题时进行更新,但这是我的最佳猜测.

I'll update this as you update your question, but here's my best guess.

此行无法编译,因为Select不会返回列表:

This line doesn't compile, because Select doesn't return a List:

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

我要冒昧地猜测您实际上是在这样做:

I'm going to hazard a guess that you're actually doing this:

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

...会产生冷的IEnumerable:只有在其实际迭代结束时才会运行.

... which produces a cold IEnumerable: one which will only run when it actually gets iterated over.

在上面的代码中,您在调用.ToArray()时对其进行迭代.但是,您描述为耗时25ms的那行同样只会产生另一个冷IEnumerable<>.这里没有任何实际的工作:

In the code above, you're iterating over it when you call .ToArray() on it. But the line you describe as taking 25ms is likewise producing nothing but another cold IEnumerable<>. No real work is being done here:

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

所以我再次冒昧地猜测您正在做更多这样的事情:

So again I'm going to hazard a guess that you're doing something more like this:

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

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

... which is going to iterate over myTasks a second time, causing Task.Run(...) to get called again for each item in someList, and then waiting for all of those tasks to complete.

换句话说,您要做两次工作,最后一次在您引用的行中进行一次.

In other words, you're doing the work twice, and one of those times in in the line that you reference at the end.

幸运的是,使用任务并行库有一种更好的方法来完成您的工作.

Fortunately, there is a better way to do what you're doing, using the Task Parallel Library.

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

这篇关于C#:为什么任务完成后要花很长时间才能获得任务t.Re​​sult?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆