【发布时间】:2015-12-09 17:17:04
【问题描述】:
我有以下代码:
static void Main(string[] args)
{
IEnumerable<int> threadsIds = Enumerable.Range(1, 1000);
DateTime globalStart = DateTime.Now;
Console.WriteLine("{0:s.fff} Starting tasks", globalStart);
Parallel.ForEach(threadsIds, (threadsId) =>
{
DateTime taskStart = DateTime.Now;
const int sleepDuration = 1000;
Console.WriteLine("{1:s.fff} Starting task {0}, sleeping for {2}", threadsId, taskStart, sleepDuration);
Thread.Sleep(sleepDuration);
DateTime taskFinish = DateTime.Now;
Console.WriteLine("{1:s.fff} Ending task {0}, task duration {2}", threadsId, taskFinish, taskFinish- taskStart);
});
DateTime globalFinish= DateTime.Now;
Console.WriteLine("{0:s.fff} Tasks finished. Total duration: {1}", globalFinish, globalFinish-globalStart);
Console.ReadLine();
}
目前,当我运行它时,运行它大约需要 60 秒。据我了解,这是因为.Net 不会为每个任务创建一个线程,而是为所有Tasks 创建一些线程,当我执行Thread.Sleep 时,我会阻止该线程执行其他一些任务。
在我的实际情况中,我有一些并行工作要做,如果失败,我必须等待一段时间才能重试。
我正在寻找除 Thread.Sleep 之外的其他东西,这将允许其他任务在其他任务的“睡眠时间”期间运行。
不幸的是,我目前正在运行 .Net 4,这使我无法使用 async 和 await(我想在这种情况下这对我有帮助。
Ps,我得到了相同的结果:
- 把
Task.Delay(sleepDuration).Wait() - 不使用
Parallel.Foreach,而是使用Task.Factory.StartNew的foreach
Ps2,我知道我可以以不同的方式处理我的真实案例,但我很想了解如何以这种方式实现它。
【问题讨论】:
-
Task.Delay.Wait()(实际上)与Thread.Sleep相同,所以很清楚为什么它没有帮助。这个问题似乎更像是“如何重试失败的任务?”那么如何开始任务。但我想重试部分取决于您的真实代码和要求。让任务等待并重试的想法总是会导致您描述的相同结果。尝试评估每个任务的结果并重新启动失败的任务。 -
Parallel.ForEach不是为了同时并行运行所有操作,而是为了优化执行以并行运行 some。await Task.WhenAll+await Task.Delay()而不是Parallel.ForEach+Thread.Sleep()确实是一个解决方案...... -
如果您需要等待一段时间,为什么不使用计时器并让失败的任务设置计时器以在 60 秒或其他时间再次运行您的方法,就像您不在线程池中睡觉一样.
-
你可能想看看Task.ContinueWith。这可以使用选项调用,以便仅在第一个任务失败时才开始继续。因此,您失败的任务可能会抛出,从而再次启动(相同的方法),尽管仍然存在等待一点的问题。抱歉,无法将这些组合成一个合格的答案。
-
@J4N:如果你在桌面上运行,你可以使用Microsoft.Bcl.Async来启用
async和await。
标签: c# .net multithreading task-parallel-library