为什么以下使用IOmniThreadPool的代码会导致访问冲突?

提姆

在我们的Delphi XE4应用程序中,我们使用MaxExecuting = 4的OmniThreadPool来提高特定计算的效率。不幸的是,我们遇到断断续续的访问冲突(例如,请参阅以下MadExcept错误报告http://ec2-72-44-42-247.compute-1.amazonaws.com/BugReport.txt)。我能够构造以下示例来说明问题。运行以下控制台应用程序后,通常在一分钟左右的时间内发生System.SyncObjs.TCriticalSection.Acquire中的访问冲突。有人可以告诉我我在以下代码中做错了什么吗,还是告诉我另一种实现预期结果的方法?

program OmniPoolCrashTest;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows, System.SysUtils,
  DSiWin32, GpLists,
  OtlSync, OtlThreadPool, OtlTaskControl, OtlComm, OtlTask;

const
  cTimeToWaitForException = 10 * 60 * 1000;  // program exits if no exception after 10 minutes
  MSG_CALLEE_FINISHED = 113; // our custom Omni message ID
  cMaxAllowedParallelCallees = 4; // enforced via thread pool
  cCalleeDuration = 10; // 10 miliseconds
  cCallerRepetitionInterval = 200; // 200 milliseconds
  cDefaultNumberOfCallers = 10; // 10 callers each issuing 1 call every 200 milliseconds

var
  gv_OmniThreadPool : IOmniThreadPool;

procedure OmniTaskProcedure_Callee(const task: IOmniTask);
begin
  Sleep(cCalleeDuration);
  task.Comm.Send(MSG_CALLEE_FINISHED);
end;

procedure PerformThreadPoolTest();
var
  OmniTaskControl : IOmniTaskControl;
begin
  OmniTaskControl := CreateTask(OmniTaskProcedure_Callee).Schedule(gv_OmniThreadPool);
  WaitForSingleObject(OmniTaskControl.Comm.NewMessageEvent, INFINITE);
end;

procedure OmniTaskProcedure_Caller(const task: IOmniTask);
begin
  while not task.Terminated do begin
    PerformThreadPoolTest();
    Sleep(cCallerRepetitionInterval);
  end;
end;

var
  CallerTasks : TGpInterfaceList<IOmniTaskControl>;
  i : integer;
begin
  gv_OmniThreadPool := CreateThreadPool('CalleeThreadPool');
  gv_OmniThreadPool.MaxExecuting := cMaxAllowedParallelCallees;
  CallerTasks := TGpInterfaceList<IOmniTaskControl>.Create();
  for i := 1 to StrToIntDef(ParamStr(1), cDefaultNumberOfCallers) do begin
    CallerTasks.Add( CreateTask(OmniTaskProcedure_Caller).Run() );
  end;
  Sleep(cTimeToWaitForException);
  for i := 0 to CallerTasks.Count-1 do begin
    CallerTasks[i].Terminate();
  end;
  CallerTasks.Free();
end.
加布

您在这里有一个难以找到的示例Task Controller需要所有者问题。发生的情况是,任务控制器有时会在任务本身之前被破坏,从而导致任务访问包含随机数据的内存。

问题场景如下所示([T]标记任务,[C]标记任务控制器):

  • [T]发送消息
  • [C]收到消息并退出
  • [C]被摧毁
  • 创建了新任务[T1]和控制器[C1]
  • [T]试图退出;在此期间,它访问由[C]管理但随后被属于[C1]或[T1]的数据破坏并覆盖的共享存储区

在Graymatter的解决方法中,OnTerminated为OmniThreadLibrary内部的任务创建一个隐式所有者,以“解决”问题。

等待任务完成的正确方法是调用taskControler.WaitFor。

procedure OmniTaskProcedure_Callee(const task: IOmniTask);
begin
  Sleep(cCalleeDuration);
end;

procedure PerformThreadPoolTest();
var
  OmniTaskControl : IOmniTaskControl;
begin
  OmniTaskControl := CreateTask(OmniTaskProcedure_Callee).Schedule(gv_OmniThreadPool);
  OmniTaskControl.WaitFor(INFINITE);
end;

我将研究用引用计数解决方案替换共享内存记录,以防止此类问题发生(或至少使它们更易于发现)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么以下使用IOmniThreadPool的代码会导致访问冲突?

来自分类Dev

为什么更正“可选参数”会导致访问冲突?

来自分类Dev

为什么以下代码会导致无限递归?

来自分类Dev

为什么以下代码会导致无限递归?

来自分类Dev

为什么此代码会引发读取访问冲突?

来自分类Dev

为什么使用defpackage会导致名称冲突?

来自分类Dev

为什么此代码会导致访问错误?

来自分类Dev

为什么这会导致访问冲突?

来自分类Dev

为什么以下代码会运行?

来自分类Dev

为什么选择樱桃总是会导致合并冲突?

来自分类Dev

为什么这会导致nullptr写入访问冲突

来自分类Dev

为什么在计时器回调中调用事件会导致以下代码被忽略?

来自分类Dev

为什么以下代码导致模板实例化?

来自分类Dev

为什么以下代码会产生分段错误?

来自分类Dev

为什么在此C ++代码中出现“访问冲突”

来自分类Dev

调用glDrawElements会导致访问冲突

来自分类Dev

从APC调用LdrLoadDll会导致访问冲突

来自分类Dev

为什么mkdir偶尔会导致访问被拒绝?

来自分类Dev

为什么此代码会导致分段错误

来自分类Dev

为什么看似等效的SecurityManager代码会导致虚假异常?

来自分类Dev

为什么这段代码会导致无限循环

来自分类Dev

为什么此代码会导致“需要对象”错误?

来自分类Dev

为什么此htaccess代码会导致重定向循环?

来自分类Dev

为什么此代码会导致与MSVC的无效对齐?

来自分类Dev

为什么我的代码会导致无限循环?

来自分类Dev

为什么这段代码会导致无效的指针?

来自分类Dev

为什么这段代码会导致无限循环

来自分类Dev

为什么基本的Swift代码会导致内存泄漏?

来自分类Dev

为什么facebook javascript登录代码会导致无限循环?

Related 相关文章

  1. 1

    为什么以下使用IOmniThreadPool的代码会导致访问冲突?

  2. 2

    为什么更正“可选参数”会导致访问冲突?

  3. 3

    为什么以下代码会导致无限递归?

  4. 4

    为什么以下代码会导致无限递归?

  5. 5

    为什么此代码会引发读取访问冲突?

  6. 6

    为什么使用defpackage会导致名称冲突?

  7. 7

    为什么此代码会导致访问错误?

  8. 8

    为什么这会导致访问冲突?

  9. 9

    为什么以下代码会运行?

  10. 10

    为什么选择樱桃总是会导致合并冲突?

  11. 11

    为什么这会导致nullptr写入访问冲突

  12. 12

    为什么在计时器回调中调用事件会导致以下代码被忽略?

  13. 13

    为什么以下代码导致模板实例化?

  14. 14

    为什么以下代码会产生分段错误?

  15. 15

    为什么在此C ++代码中出现“访问冲突”

  16. 16

    调用glDrawElements会导致访问冲突

  17. 17

    从APC调用LdrLoadDll会导致访问冲突

  18. 18

    为什么mkdir偶尔会导致访问被拒绝?

  19. 19

    为什么此代码会导致分段错误

  20. 20

    为什么看似等效的SecurityManager代码会导致虚假异常?

  21. 21

    为什么这段代码会导致无限循环

  22. 22

    为什么此代码会导致“需要对象”错误?

  23. 23

    为什么此htaccess代码会导致重定向循环?

  24. 24

    为什么此代码会导致与MSVC的无效对齐?

  25. 25

    为什么我的代码会导致无限循环?

  26. 26

    为什么这段代码会导致无效的指针?

  27. 27

    为什么这段代码会导致无限循环

  28. 28

    为什么基本的Swift代码会导致内存泄漏?

  29. 29

    为什么facebook javascript登录代码会导致无限循环?

热门标签

归档