【发布时间】:2014-05-28 09:01:24
【问题描述】:
在我们的 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.
【问题讨论】:
-
这看起来和另一个问题一样。你真的应该只问一个。我建议你删除其中一个。您能否进一步简化这一点。理想情况下,应该有一个没有 UI 的 .dpr 文件。一个控制台应用程序。
-
感谢您的反馈!我现在删除了另一个问题并简化了示例代码。
-
出色的工作。现在真的是超级SSCCE。如果允许,我会再次投票!
标签: delphi threadpool access-violation omnithreadlibrary