Compute
函数内部有大量、持久的计算(数十分钟)。我无法编辑此函数,我无权访问源代码。
List<Action> parallelActions = new();
for (int i = 0; i < 1000; i++)
{
parallelActions.Add(() => Compute(i));
}
Parallel.Invoke(parallelActions.ToArray());
如果循环执行时间超过 maxTime
秒,我想停止循环执行。您知道如何通过立即停止执行来结束并行循环吗?
我尝试添加CancellationToken
:
List<Action> parallelActions = new();
for (int i = 0; i < 1000; i++)
{
parallelActions.Add(() => Compute(i));
}
using CancellationTokenSource cts = new(new TimeSpan(0, 0, maxTime));
ParallelOptions parallelOptions = new() { CancellationToken = cts.Token };
Parallel.Invoke(parallelOptions, parallelActions.ToArray());
问题是,即使我添加了 CancellationToken
,已经启动的 Compute
功能也不会停止,所以我必须等待很长时间才能完成。如何更改?
更多信息:我的目标是 .NET 7 平台。每个单独的Compute
调用平均需要几十分钟才能完成。
最佳答案
recommended way以非合作方式强制中止工作的方法是在单独的可执行文件上运行工作并通过终止进程来中止工作。这是保护主可执行文件的状态免遭损坏的唯一方法。即使您的目标是支持 Thread.Abort
的 .NET 平台API 与 .NET Framework 一样,使用它会危及应用程序的稳定性及其行为的正确性。
.NET 7 引入了 ControlledExecution.Run
方法,该方法执行受控的 Thread.Abort,而不实际终止当前线程。终止会自动取消,并显示 Thread.ResetAbort
。使用 ControlledExecution.Run
方法生成 compilation warning :
The
ControlledExecution.Run(Action, CancellationToken)
method might corrupt the process, and should not be used in production code.
虽然Thread.Abort
是“受控的”,但它可能像原始Thread.Abort
一样容易地破坏应用程序的状态。在执行单个 CPU 指令时,线程会在任意时刻中止。不是方法,而是CPU指令。大多数 .NET API 都编译为多个 CPU 指令,并且未针对部分执行其指令集后的恢复进行强化。
假设您了解风险,以下是使用它的方法:
using CancellationTokenSource cts = new();
ParallelOptions options = new()
{
CancellationToken = cts.Token,
MaxDegreeOfParallelism = 20 // Configurable
};
ThreadPool.GetMinThreads(out _, out int cpt);
ThreadPool.SetMinThreads(options.MaxDegreeOfParallelism, cpt);
cts.CancelAfter(TimeSpan.FromMinutes(120));
Parallel.For(0, 1000, options, index =>
{
ControlledExecution.Run(() =>
{
Compute(index);
}, cts.Token);
});
在上面的例子中 ThreadPool.SetMinThreads
配置 ThreadPool,以便它立即创建 Parallel.For 所需的所有线程,以便从一开始就达到所需的并行度。如果省略它,ThreadPool
可能需要一些时间才能创建所需数量的线程。
另一种想法是绕过ThreadPool
并使用专用线程。您可以找到here自定义 TaskScheduler
,为每个任务创建专用后台线程。
关于c# - 如何强制结束 Parallel.Invoke 循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77071891/