没有线程的Delphi事件处理

时间:2012-10-12 14:27:27

标签: multithreading delphi event-handling delphi-7

我不是Delphi的专家,我对消息流以及事件和回调的处理只有基本的了解。我正在尝试调试D7中需要将前台程序(通过按钮单击启动)与后台发生的消息接收和处理(由组件处理)组合在一起的应用程序。它们都可以独立工作,但是当我在一个程序中将它们组合在一起时,消息接收不起作用。

现有应用程序已经具有在按钮单击时发送消息的功能过程,并且它可以在运行时接收消息而不处理任何按钮。

正常的消息接收由一个组件处理,该组件将我的处理程序(OnInput)作为事件调用。我的处理程序将消息放入ListBox。

我正在尝试编写一个在循环中发送消息并等待响应的过程。 (伪代码):

   for N := 0 to nsequence do begin
       prevcount := ListBox1.items.count; 
       SendMessage(mymessage);  // request the response
       sleep(500); // allow time for response to arrive
       for 0 to timeout do begin
           sleep(100); 
           application.processmessages;  {allow processing to handle incoming message}
           if ListBox1.items.count > prevcount then break;  {has the message arrived?}
           end;
       if ListBox1.items.count = prevcount then exit: {timeout -- fail}
       end;

我认为这应该可以在没有线程的情况下完成,但是永远不会收到消息。它总是超时。

是否可以从application.processmessages调用组件事件处理程序?当应用程序正在运行且空闲时,输入消息可正常工作,但在执行过程时则不能正常工作。除了调用application.processmessages之外还需要什么来使应用程序处理消息并调用相关的过程来处理它们?

要跟踪传入消息,路径将从Windows MMSystem回调开始。当MIDI输入端口打开时,回调设置为指向处理程序:procedure midiHandler

在midiHandler中,事件被放入循环缓冲区:CircbufPutEvent(thisBuffer,@ thisEvent)。

然后将消息发回给应用程序:PostMessage(thisCtlInfo ^ .hWindow,mim_Data,0,0)

该消息由以下内容处理:procedure TMidiInput.MidiInput(var Message:TMessage); 在该过程中,有一个调用:FOnMIDIInput(Self);

这些事件在组件的界面中定义为:

{ Events }
FOnMIDIInput: TNotifyEvent; { MIDI Input arrived }

在已发布的情况下,我们有:

{ Events }
property OnMidiInput: TNotifyEvent read FOnMidiInput write FOnMidiInput;
property OnOverflow: TNotifyEvent read FOnOverflow write FOnOverflow;

在Object Inspector中,OnMidiInput事件链接到过程MIDIInput1MidiInput;

程序MIDIInput1MidiInput首先调用GetMidiEvent:

with (Sender As TMidiInput) do
    begin
    while (MessageCount > 0) do
        begin

        { Get the event as an object }
        thisEvent := GetMidiEvent;

GetMidiEvent从循环缓冲区中读取消息。 MIDIInput1MidiInput过程执行一些检查和验证,并最终将消息存储在ListBox1中。

PS - 输入组件具有一个属性,该属性返回循环缓冲区中排队消息的计数。我在等待循环超时时检查它,并报告0条消息。所以回调显然没有进入midiHandler程序。

1 个答案:

答案 0 :(得分:0)

感谢Jay的评论,我开始深入研究调用过程时被禁止的内容。

为了简化我的伪代码,我没有包括对SendMessage过程有两个顺序调用的事实 - 一个用于设置参数,另一个用于在回复中请求数据。我不认为输出组件和输入组件之间存在交互,因为它们是分开的。

但我没有意识到发送组件可以与自己进行交互。通过SendMessage代码,我发现它在完成发送时会向自己发送一条消息,重新启用它以接受另一条消息。第二条消息(响应请求)未被发送,因为发送过程未重新启用。

在对SendMessage过程的两次调用之间调用application.processmessages似乎解决了这个问题。