DLL線程中坑爹的Synchronize?
1, 緣起
某次開發語音對講windows程序,采用delphi語言,及delphix的TDXSound控件。
DXSound提供了TSoundCaptureStream類,可以實現指定頻率、位數、聲道的聲卡錄音。在其OnFilledBuffer事件處理中,將音頻數據發給指定設備就能實現流式對講。
先寫了一個測試EXE程序,運行OK。然後需要將其功能封裝為DLL函數,供其它應用程序開發時調用,封裝完畢,結果發現麥克風的聲音發送不出去。WTF?
2,分析
debug發現,調用DLL開始對講函數後,OnFilledBuffer中的回調事件代碼一直未被執行。這在exe程序中是不存在的。記得uDPServer控件有類似的毛病,如果不設置為其ThreadedEvent屬性為True,那麽在DLL中其ONUDPRead事件基本上也是收不到任何信息。
但DXSound中有類似的屬性設置嗎?查看DXSounds單元的源碼,發現TSoundCaptureStream有一個FNotifyThread屬性(又是線程!),當調用start方法開始捕捉聲卡時,會創建一個TSoundCaptureStreamNotify通知線程,而這個通知線程調用了Synchronize(Update)方法向主線程發送捕捉到了聲卡信息。
查詢資料發現,若工程文件是DLL而不是EXE的話,Application默認不創建窗口句柄,因此Synchronize 向Application發送消息根本無法響應。
參見:https://www.cnblogs.com/enli/archive/2010/09/28/1837728.html
3,解決
解決方案也是采用了上文中提供的方法,在DLL的l工程文件中加入以下語句 ,問題解決。
Application.Initialize; if Application.Handle = 0 then begin Application.CreateHandle; end; Application.Run;
DLL線程中坑爹的Synchronize?