在我们的Delphi XE4应用程序中,我们使用的是一个OmniThreadPool,MaxExecuting = 4来提高某种计算的效率.不幸的是,我们遇到间歇访问冲突时遇到麻烦(参见例如以下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 needs an owner问题的例子.发生什么是任务控制器有时在任务本身之前被破坏,并导致任务访问包含随机数据的内存.

有问题的情况就是这样([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;

我将考虑用引用计数的解决方案替换共享内存记录,这将解决这种问题(或者至少使它们更容易找到).

delphi – 为什么使用IOmniThreadPool的以下代码会导致访问冲突?的更多相关文章

  1. ios – 我在哪里可以找到用于创建IPad应用程序的Delphi资源?

    我之前一直在使用Delphi并且一直都是Windows家伙.我的妻子为我的生日买了一台新的iPad,我昨晚第一次使用它.哇!…

  2. 如何从命令行部署OSX或IOS Delphi项目?

    我正在使用像这样的脚本构建我的Delphi应用程序现在我想添加一个选项将应用程序部署到OSX系统修改这样的脚本,那么可以从命令行部署OSX或IOSDelphi项目吗?

  3. 如何检查Android和iOS上的网络是否可用(Delphi XE5)

    解决方法试试这个:

  4. 使用嵌套线程错误终止应用程序

    如果我使用一个启动了嵌套线程的线程,那么终止应用程序时会遇到问题。如果最深的嵌套线程卡住,则应用程序终止时会发生错误。在其他情况下,问题不会出现。据我所知,tSync.Free不会等待TCP.Connect完成并自行关闭。TCP.Connection在超时结束后无处返回。

  5. 通过gsdll32.dll与Delphi 11组合PDF

    我已经使用这个代码10多年了,它突然停止工作。该程序读取一个pdf文件列表,并输出一个包含列表中所有文件的pdf文件。它使用gsapi.pas包装单元。多年来,我只需要从Ghostscript.t下载一个更新版本的gsdll32.dll文件,就可以兼容更新版本的pdf文件格式。我发现他们有了一个新的翻译,也许这与此有关?请注意,在Ghostscript中使用等效的命令行本身效果良好。在我看来,他们改变了调用API的方式。如果有任何帮助,我将不胜感激。我确实尝试了添加开关“-dNEWPDF=false”,但

  6. Windows 10中的内存泄漏Delphi Seattle中的TNotification?

    我正在我的应用程序中实现Windows10通知.但是,下面的代码显然会给出1个TNotification对象和2个字符串的备忘录泄漏,但我在块的末尾释放了对象:我做了一些愚蠢的事情,或者在通知的实施中是否存在内存泄漏?

  7. 如何处理Windows 7的125%或150%放大率(Delphi)

    Windows7已添加其控制面板,外观和个性化,显示设置,放大文本和其他项目125%或150%的功能.完成后,我的Delphi2009程序的表单和对话框的一些内容被切断.我需要做些哪些更改才能确保在Windows7的任何放大设置下,我的所有表单和对话框都能正常显示.这听起来像是指文本大小设置,它在Windows中以各种形式存在多年,Delphi形成了与此设置的交互以及它们的自动缩放.我没有在这里检

  8. 是默认情况下能够处理vista / win7 UAC的delphi 2010程序

    或者你必须自己包括它?如果是,给你什么级别的特权?我的程序修改了一个注册密钥,它可以在没有对.res文件进行任何修改的情况下这样做吗?一个附带问题:是否有一个组件/专家可以像delphi2010一样自动生成/包含.res文件在我的delphi7和delphi2007项目中?

  9. windows – 我需要避免尝试更新连接到TSQLQuery的Delphi TClientDataset中的非物理字段

    Precis:我的代码试图更新DelphiXETClientDataset中的非物理字段(连接到带有sql属性集的TsqlQuery),这些字段是作为运行时Open命令创建的.我有一个连接到连接到TsqlConnection的TsqlQuery的TDatasetProvider的TClientDataset.这些对象中的前3个被封装在库中的几个类中,我在几个项目的许多地方使用它们.这些类在运行时创

  10. windows – Delphi中的跨应用程序拖放

    我想为WindowsXP创建一个Delphi应用程序,它允许删除从Windows资源管理器或其他支持此操作的应用程序拖动的文件.反之亦然?当用户从我的应用程序中拖动图标时,我应该能够将拖动对象的内容设置为自定义数据.我的目标是创建一个自定义应用程序工具栏,我可以在其上删除应用程序并显示其图标或从中拖动应用程序或其他实体.如何才能做到这一点?

随机推荐

  1. delphi – 主窗口按进程名称处理

    DelphiXe,Win7x64如何从进程名称(exe文件的完整路径)获取主窗口句柄,或至少一个类或窗口名称(如果该进程只有一个窗口).例:解决方法我同意Petesh的说法,你需要枚举顶级窗口并检查创建它的进程的模块文件名.为了帮助您开始枚举顶级窗口,这是一个delphi实现.首先,当你回调给你时,你需要一些与EnumWindows方法通信的方式.为此声明一条记录,该记录将保存您要查找的模块的文件

  2. 如何在Delphi中纯粹通过RTTI信息(即不使用任何实际对象实例)获取TObjectList的子项类型?

    我正在使用RTTI实现用于流式传输任意Delphi对象的通用代码,并且为了使其工作(更具体地说,为了使加载部分工作),我需要以某种方式获得TObjectList的子项类型<T>不使用任何实际对象实例的字段.要求不使用任何实际对象实例的明显原因是,在从流加载对象的情况下(仅基于要加载的对象的类类型的知识),我将不会有任何实例在加载完成之前完全可用–我宁愿只能访问相关类的纯RTTI数据.我希望能

  3. inno-setup – Inno Setup – 安装程序背景图片

    图像作为安装程序背景如何用inno5.5.9做到这一点?

  4. inno-setup – Inno Setup – 如何添加多个arc文件进行解压缩?

    使用InnoSetup解压缩弧文件.我希望有可能解压缩多个arc文件以从组件选择中安装文件(例如).但仍然显示所有提取的整体进度条.这可能吗?的回答的修改预备是相同的,参考其他答案.在ExtractArc中,为要提取的每个存档调用AddArchive.

  5. delphi – 如何在DataSet的帮助下在TAdvStringGrid中显示数据库中的BLOB图像

    解决方法CreateBlobStream正在创建一个TStream对象,而不是TMemoryStream.由于您不想将JPG写入数据库,因此应使用bmRead而不是bmReadWrite.我不习惯sqlite,但你必须确保使用合适的二进制日期类型.为了确保存储的图像真的是JPG,您应该编写JPG以进行测试,例如:

  6. inno-setup – 在Inno Setup的Code部分下载程序后运行程序

    如何运行我通过Internet下载的应用程序,在代码部分中使用,并等待该应用程序完成运行.我有,使用InnoTools下载程序,下载这两个文件,我想,在第二个完成下载后运行该下载,或jdk-8u111-windows-x64.exe,然后继续安装.解决方法使用其他下载插件,而不是ITD(请参阅下面的原因).例如,InnoDownloadPlugin.当您包含idp.iss时,它定义了一个全局IDP

  7. progress-bar – Inno Setup Run部分的简单进度页面

    我的安装程序非常简单,它基本上是:>欢迎页面>进展页面>最终页面欢迎页面和最终页面是标准页面.在Progress页面,我正在静默安装一堆其他程序.实际的脚本是在[Run]部分中安装每个程序.问题是酒吧达到100%然后停留在那里.我只能更改消息文本.我想要实现的是使用Pascal脚本显示进度,例如:这样我就可以显示更准确的进度条.这就是我所拥有的:问题是,当我构建安装程序时,它不显示欢迎页面.我做错了什么?

  8. delphi – 如何使“显示/隐藏桌面图标”设置生效?

    下面的代码调用SHGetSetSettings函数来隐藏桌面图标但它只是从视图菜单中取消选中“显示桌面图标”.我打电话给SHChangeNotify;更新桌面,但这不起作用?解决方法isa,要刷新桌面,您可以将F5键发送到progman窗口隐藏桌面图标的另一种方法是再次显示

  9. inno-setup – Inno Setup – 避免显示子安装程序的文件名

    我试图使用InnoSetup–Howtohidecertainfilenameswhileinstalling?(FilenameLabel)的想法Theonlysuresolutionistoavoidinstallingthefiles,youdonotwanttoshow,usingthe[Files]section.Installthemusingacodeinstead.UsetheEx

  10. inno-setup – Inno Setup磁力链接下载实施

    我目前正在使用InnoDownloadPlugin为我的安装程序下载文件,这个问题最大的问题是faila正确下载文件.因为连接不良等诸多原因.我想添加一种替代方法来下载文件,因此用户可以选择是否需要常规方式或torrent方式.我知道我可以使用aria2c.exe应用程序(https://aria2.github.io/),有人可以帮我实现它的inno设置代码吗?我需要的是使用torrent(ar

返回
顶部