1. 程式人生 > >DLL線程中坑爹的Synchronize?

DLL線程中坑爹的Synchronize?

工程文件 一個 creat init eat 因此 測試 錄音 捕捉

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?