如果其中一个主题执行时间超过2分钟,我正在寻找停止Parallel.ForEach
的解决方案。
我认为下一个解决方案因为x2额外线程而不是很好:
Parallel.ForEach(items, (item, opt) =>
{
var thread = new Thread(() => { /* a process */ });
thread.Start();
bool finished = thread.Join(TimeSpan.FromMinutes(2));
if (!finished)
{
thread.Abort();
opt.Stop();
}
});
您是否知道更好的解决方案?
答案 0 :(得分:1)
首先,我想要注意Parallel
类不会为您的每个项创建一个线程,它将使用默认的ThreadPool
,默认情况下线程数等于处理器的核心数。您的代码中的其他问题是您在工作2分钟后没有停止所有任务,您只能取消您等待两分钟的任务。
我建议您从代码中删除Thread
用法,并使用single CancellationToken
for them或a Timeout for it创建一个Tasks
数组,并{ {3}}。此外,您的代码应明确检查令牌是否有待取消。
所以你的代码可能是这样的:
var cts = new CancellationTokenSource();
// two minutes in milliseconds
cts.CancelAfter(2000 * 60);
var tasks = new List<Task>();
foreach (var item in items)
{
// this is needed because of closures work in C#
var localItem = item;
tasks.Add(Task.Run(() =>
{ /* a process with a localItem here */
// this check should be repeated from time to time in your calculations
if (cts.Token.IsCancellationRequested)
{
cts.Token.ThrowIfCancellationRequested();
}
}
// all tasks has only one token
, cts.Token)
}
// this will cancel all tasks after 2 minutes from start
Task.WaitAll(tasks.ToArray(), TimeSpan.FromMinutes(2));
// this will cancel all tasks if one of them will last more than 2 minutes
Task.WaitAll(tasks.ToArray());
<强>更新强>
正如您所说,每个项目都是独立的,您可以为每个任务创建CancellationTokenSource
,但是,正如@ScottChamberlain所说,在这种情况下,太多任务将同时运行。您可以a timeout for TaskFactory
,使用一些start them all(或write your own TaskScheduler
),或者只需使用Parallel
类正确设置Semafor
。