"Emergency" 全线程 IOmniParallelTask​​ 终止

"Emergency" termination of omnithread IOmniParallelTask

背景

我有一个单元测试,我在其中检查我的处理程序代码在多线程压力下是否表现良好:

procedure TestAppProgress.TestLoopedAppProgressRelease_SubThread;
begin
  var bt:=Parallel.ParallelTask.NumTasks(1).NoWait.Execute(
    procedure
    begin
      SetWin32ThreadName('TestLoopedAppProgressRelease_SubThread');
      RunLoopedAppProgressRelease;
    end
  );
  lSuccess:=bt.WaitFor(cRunLoopTimerMilliSecs*2);
  if not lSuccess then
    bt.Terminate; // emergency termination, unit test failed <<< How do I do this?
  Check(lSuccess,'Failed to finish within expected time');
end;

万一并行线程未能在预期时间内完成,则说明出了点问题,我的检查失败了。 不幸的是,如果并行任务挂起,它永远不会结束,并且我的单元测试会冻结,因为在等待永无止境的并行任务完成的例程结束时释放了 bt 接口。

所以我需要以 evil 方式关闭我的并行任务。

注意 1:这是一个单元测试,我不太关心线程清理:如果单元测试失败,无论如何都需要修复一些东西。我只是不希望我的整个单元测试套件 hang/freeze,而只是报告失败并继续我套件中的下一个测试。

注意 2:可以省略 Numthreads(1) 或任意数量的线程。

问题:如何强制终止IOmniParallel任务?

好吧,我应该做更好的研究。这是单后台线程的解决方案,只需使用IOmniTaskControl接口:

procedure TestAppProgress.TestLoopedAppProgressRelease_SubThread;
begin
  var lTask:=CreateTask(
    procedure (const aTask:IOmniTask)
    begin
      RunLoopedAppProgressRelease;
    end,
    'TestLoopedAppProgressRelease_SubThread'
  );
  lTask.Run;
  var lSuccess:=lTask.WaitFor(cRunLoopTimerMilliSecs*2);
  if not lSuccess then
    lTask.Terminate; // emergency termination, unit test failed
  Check(lSuccess,'Failed to finish within expected time');
end;

如果你想在多个子线程中 运行 它,你需要将它包装在 IOmniTaskGroup:

procedure TestAppProgress.TestLoopedAppProgressRelease_MultiSubThread;
const cThreads=4;
begin
  var lTaskGroup:=CreateTaskGroup;
  for var i:=1 to cThreads do
  begin
    var lTask:=CreateTask(
      procedure (const aTask:IOmniTask)
      begin
        RunLoopedAppProgressRelease;
      end,
      'TestLoopedAppProgressRelease_SubThread '+i.ToString
    );
    lTaskGroup.Add(lTask);
  end;
  lTaskGroup.RunAll;
  var lSuccess:=lTaskGroup.WaitForAll(cRunLoopTimerMilliSecs*2);
  if not lSuccess then
    lTaskGroup.TerminateAll; // emergency termination, unit test failed
  Check(lSuccess,'Failed to finish within expected time');
end;

在我的调试器中使用 delays/breakpoints 我验证了单元测试(错误)处理现在按预期工作。这包括由于终止线程导致的预期内存泄漏。

我仍然觉得 IOmniParallelTask 应该有一个 Terminate 类似于 IOmniTaskIOmniTaskGroup

中的方法