多线程 – Synchronize()挂起线程

我在Delphi中编写了一个dll库,它创建了多个线程.让我一步一步地描述问题.我很抱歉提前做了很长时间的描述:-(.

让我们暂时忘掉图书馆.我创建了一个Windows应用程序,它将从几个摄像头呈现视图.我创建了一个窗口,用于显示来自单个摄像头的视图,它包含一个TImage控件.有一个线程(一个TThread后代)每隔几毫秒从摄像头下载当前图像,并将其分配给该窗口的TImage控件(使用Synchronize()方法).应用程序在启动时创建该窗口的多个实例(每个窗口都有一个单独的线程),因此您可以同时从多个摄像头中查看实时视图.更重要的是,所有这些查看窗口都是主应用程序窗口的父级,因此它们出现在其中.

一切正常,直到我决定将这两个窗口放入dll库.我发现有必要出于某些原因,但现在它们并不重要.所以我创建了一个新的dll库,将现有的主窗口和摄像机视图窗口添加到项目中,并导出了一个创建并返回主窗口实例的函数.创建主窗口时,它会创建几个摄像机视图窗口,使其自身成为父窗口.

然后,出于测试目的,我创建了一个应用程序,它从库中导入上面提到的dll函数,并在启动时调用它来获取主窗口的实例;然后只是在屏幕上显示它(处于非模态状态).

当我启动应用程序时,我发现我无法从任何相机获得单个图像.当我调试它时,我注意到当线程调用Synchronize()方法时,它会永远挂起.在将这两个窗口放入dll之前没有发生过.

这是我的问题.说实话,这是我对图书馆的第一种方法,到目前为止,我必须解决许多其他问题.您可能想知道为什么我使用Windows而不是框架……所以每当我在dll中创建一个TFrame实例时,我会得到一个例外,说“控件xxx没有父窗口”.我不知道该怎么办,所以我改用了windows :-(.

你能告诉我如何处理同步问题吗?当应用程序启动时,主线程似乎没有以任何方式被阻止它接受点击按钮等.那么问题是什么?

请帮忙!

先感谢您!!

最佳答案
当您调用TThread.Synchronize时,线程和方法指针将添加到Classes.pas中的全局SyncList:TList.在主exe的TApplication.Idle例程中调用CheckSynchronize,它检查SyncList,但是它将检查exe中的版本而不是DLL中的版本.最终结果,永远不会调用您的同步方法.

最简单的解决方法是从DLL切换到包,这将消除重复的SyncList.

另一种方法是覆盖exe的Application.OnIdle回调,并手动调用DLL的CheckSynchronize.你需要一些应用程序的帮助,因为你的DLL也有一个Application对象,而且那个不起作用.

转载注明原文:多线程 – Synchronize()挂起线程 - 代码日志