在主线程上下文中执行代码(Lazarus)

4
我需要在主线程的上下文中执行一些代码。我使用的是Lazarus + FPC。我从DLL(如果在Linux上则为共享库)内部的线程接收到一个事件,我的回调函数被调用。请注意,此函数不是任何类的成员,而是一个带有“cdecl”指令的独立传统函数。
我必须为我接收到的每个这样的消息触发相应的属性事件处理程序。并且这些事件必须在主线程的上下文中传递。我知道有两种解决方案:
1. PostMessage 2. Application.QueueAsyncCall
第一个解决方案可以,但它需要一个窗口句柄。由于这是库代码,因此没有句柄可用。AllocateHWND不是跨平台的选择。我知道我可以创建一个虚拟窗体,但这是一个非常糟糕的解决方案。
第二个解决方案可以正常工作,但我有一个问题,即调用直到我在应用程序内移动鼠标等操作才会被处理。也许我做错了什么,我不知道。就像我的调用只有在消息处理开始时才被处理一样。但这可能需要很长时间。
因此,我想知道最佳解决方案是什么(可能是QueueAsyncCall),以及如何确保我的消息(调用)在可接受的时间内被处理?
1个回答

1

你不能百分之百确定,就像在任何非实时系统中一样。如果主线程挂起,它将不会检查主循环中的消息或其他事件。这是正常的。

唯一能做的就是避免在主线程中执行可能需要很长时间的操作。判断什么是必要的,什么是不必要的,这是行业内的诀窍。一些实时导向的人将所有文件系统访问移动到线程中,并且严格保持GUI只用于UI,因为如果用户配置了网络共享路径,那么共享问题很容易导致长时间等待,甚至几分钟。

如果我看一下application.queueasynccall,我没有看到线程安全处理(没有锁定或锁定队列),所以排除这个。

我知道postmessage在非Windows上被Lazarus某种程度地模拟,我检查了实现,它确实有锁,所以我认为它是多线程安全的。


我非常清楚我不能百分之百确定,但我的应用程序什么也没做,直到我移动鼠标才会处理调用。所以我最好使用PostMessage。但缺点是AllocateHWND还没有以跨平台的方式实现。或者它已经实现了吗?我认为Application.QueueAsyncCall是线程安全的。我会检查实现。谢谢你的回答。虽然我在多线程环境中有很多经验,但我对Lazarus还很新。因此出现了问题 :) - Runner
恐怖的:) 它确实没有任何线程安全性。除了 PostMessage 之外,是否有任何消息传递的替代方法?我的意思是简单的,没有 IPC 或 TCP/IP? - Runner
不是真的。我认为他们在其他平台上实现postmessage仿真的麻烦是有原因的。 - Marco van de Voort
Runner: 你想要向主线程发送消息,该线程具有form.handle或application.handle。另一种方法是以多平台方式或进程间通信的方式向LCL控制之外的代码发送消息,这将很难甚至不可能实现。仿真是有限的。 - Marco van de Voort
查看 tthread.queue 是否存在(D2006+,不确定是否已经在 FPC 中) - Marco van de Voort
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接