2012-10-12 149 views
0

我不是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 MMS系統的回調開始。 MIDI輸入端口打開時,回調被設置爲指向處理程序:procedure midiHandler

在midiHandler中,事件被放入循環緩衝區:CircbufPutEvent(thisBuffer,@thisEvent)。

然後一個消息被髮回到該應用程序:PostMessage的(thisCtlInfo^.hWindow,mim_Data,0,0)

即消息被處理的:程序TMidiInput.MidiInput(VAR消息: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程序。

+0

看起來問題出現在'mymessage'消息處理程序中。因爲它似乎依賴於閒置狀態。你也應該在你的問題中包含該代碼。 – Jay

+0

@Jay - 謝謝。我將編輯問題以追蹤傳入消息的流向。 (它在一個我沒有寫的組件中處理,但我有源代碼)。 – tim11g

+0

你能跟隨這一連串的事件,看看它在哪裏迷路? – tim11g

回答

0

感謝Jay的評論,我開始深入研究當程序被調用時被禁止的內容。

爲了簡化我的僞代碼,我沒有包含這樣一個事實,即有兩個對SendMessage過程的連續調用 - 一個用於設置參數,另一個用於在回覆中請求數據。我不認爲輸出和輸入組件之間存在交互,因爲它們是分開的。

但我沒有意識到發送組件可以與自己進行交互。仔細查看SendMessage代碼,我發現它在發送完成後自己發送一條消息,這會重新使其能夠接受另一條消息。第二條消息(響應請求)未發送,因爲發送過程沒有得到重新啓用。

將兩個調用SendMessage過程之間的application.processmessages調用似乎已解決此問題。

+0

事實上,Application.ProcessMessages可以工作一些奇蹟,但它也可以引導一些惡夢。 –

+4

Application.ProcessMessages永遠不可能是答案,永遠不會弄亂消息循環,清理你的設計...... – whosrdaddy

+2

肯定有時間重構(修復你的組件設計)。一個額外的消息發送或不發送和您的設計中斷。例如,也許您應該使用Dec/Inc來處理類中的整數「Locked」字段,而不是布爾型的「IsBusy:Boolean」字段。每當你覺得給Application.ProcessMessages添加一個調用時,你應該把這個調用包裝在一個你命名爲'DoRandomUnpredictableStuffWhilePrayingFerventlyThatThisAllWorks'的過程中。 –