【问题标题】:Firemonkey message handling using TMessageManager and TThread.Queue使用 TMessageManager 和 TThread.Queue 处理 Firemonkey 消息
【发布时间】:2014-10-03 09:31:06
【问题描述】:

像许多其他 Firemonkey 开发人员一样,我需要一个通用的多平台解决方案来将消息从线程发送到主线程(以替换 PostMessage)。我需要它也可以在 iOS 上工作。

François Piette 的解决方案适用于 Android 和 Windows,但不适用于 iOS: TMessagingSystem.

但是,我认为通过将“新”TMessageManager 与 TThread.Queue() 结合使用可以更简单地完成。但是没有人使用这种方法发布了真正有效的代码(例如this one is not complete)。

您是否有想要与社区分享的经过测试的实施(或者只是建议如何正确实施)?

【问题讨论】:

  • 使用TThread.Queue 和闭包。两者都适用于任何平台。 uweraabe.de/Blog/2011/01/30/…
  • 请注意,TThread.Synchronize()TThread.Queue() 在 XE7 之前的 每个 版本的 FireMonkey 中都被破坏了。有关详细信息和解决方法,请参阅 QC #123579

标签: delphi firemonkey delphi-xe6


【解决方案1】:

好的,这是我的实现。我没有使用 TMessagingSystem,因为它似乎只是增加了复杂性(至少对于我的情况而言)。到目前为止它工作正常,但如果有人有改进建议,我会很乐意改进它。

我查看了Uwe Raabe 的解决方案,但我想让它在我正在转换为 FMX 的大型代码库中更直接、更容易实现。 使用下面的解决方案,我可以简单地将所有 PostMessage() 替换为 gMessageHandler.PostMessage(删除 win 句柄参数),并将表单中的消息函数添加到 tMainForm.MessageCallBack。

我创建了一个小单元,我可以在任何需要 PostMessage 函数的地方包含它。那些地方不需要知道表格:

unit MessageHandler
interface
tAllOSMessage = procedure(aMessageID, aData1, aData2: integer) of object;
tAllOSMessageHandler = class
private
  fOnMessage : tAllOSMessage;
public
  constructor Create(aMessageCallBack: tAllOSMessage);
  procedure PostMessage(aMessageID, aData1, aData2: integer; aSourceThread: TThread = nil);
end;

var
  gMessageHandler: tAllOSMessageHandler;

implementation

constructor tAllOSMessageHandler.Create(aMessageCallBack: tAllOSMessage);
begin
  fOnMessage := aMessageCallBack;
end;

procedure tAllOSMessageHandler.PostMessage(aMessageID, aData1, aData2: integer; aSourceThread: TThread);
begin
  if aSourceThread=nil then
    aSourceThread := TThread.CurrentThread;
  aSourceThread.Queue(nil, procedure
                           begin
                             if Assigned(fOnMessage) then
                               fOnMessage(aMessageID, aData1, aData2);
                           end  );
end;
end.

然后我将这些行添加到主窗体单元:

//Added to main form:
tMainForm = class(TForm)
...
procedure MessageCallBack(aMessageID, aData1, aData2: integer);

//Added to MainFormCreate
gMessageHandler := tAllOSMessageHandler.Create(MessageCallBack);

//Added to MainFormDestroy
FreeAndNil(gMessageHandler)

procedure tMainForm.MessageCallBack(aMessageID, aData1, aData2: integer);
begin
  case aMessageID of
    MyMessage1 :  MyFunction1(aData1,aData2);
    ...
  end;
end;

【讨论】:

  • 你为什么要打扰 aSourceThread?只需使用 TThread.Queue(nil, ...) 基本上是一样的。
  • @ciuly:太好了,那么源代码可以变得更加简单:-) 我不记得为什么 aSourceThread 进来了。
猜你喜欢
  • 2012-02-29
  • 2018-07-06
  • 2011-11-21
  • 2019-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
相关资源
最近更新 更多