Delphi:TComPort封裝在DLL中,通訊時無法接收串口資料的解決辦法

來源:互聯網
上載者:User
現象:將Tcomport(版本:ComPort Library ver. 3.0   )封裝在DLL中,進行串口通訊時,無法接收資料! 解決辦法:在建立組件時,只需要更改一個屬性的設定就可以了。如下所示:          //DLL入口                      talencaport:=ttalencaport.Create(nil);           talencaport.port:='COM1';           talencaport.SyncMethod:=smWindowSync;           talencaport.OnRxChar:=talencaport.readbuf;紅色加粗的代碼就是關鍵的一句代碼!加入此句代碼後,在DLL中發送與接收資料就與在表單上使用一樣。  分析:由於工作需要,一直使用DELPHI5,DELPHI7兩個版本進行開發。在DELPHI5中,將TCOMPORT封裝在DLL中使用,沒有任何的異常。後來抱成DELPHI7後,當時以為,同樣的代碼,應當沒有什麼問題。於是,編譯。成功!哈!原來版本升級這麼容易!也沒有多想,沒有測試,就把這事情放在了腦後。-_-!! 時間過了一個月,公司有裝置要進行測試,因此,自己很高興地把新的東西用來測試,結果,所有的通訊指令均是失敗(無資料)!頭頓時就要炸了。。。。。。 還好,是自己測試,有問題還算是可以補救的。仔細看源碼,與DELPHI5下的源碼是一樣的,為什麼在DELPHI7下就接收不到資料呢?看來問題還是在TCOMPORT本身上。(:),偶還是粉相信DELPHI實力的!:))一看DLL入口代碼:talencaport:=ttalencaport.Create(nil);              talencaport.port:='COM1';              talencaport.OnRxChar:=talencaport.readbuf;似乎也看不出什麼問題來。 心想,是不是在發送完資料後,要延時一點時間呢,於是在發送完資料後,加入一個延時100ms和小過程(這個延時時間跟我們的裝置相關),結果發現還是收不到資料。看來不是這個延時的問題。延時過程代碼: var Com_waittime:cardinal;    Com_waittime:=gettickcount;    While gettickcount- Com_waittime<100 do application.processmessages; 沒有辦法,只能看TCOMPORT源碼了。一看源碼,TCOMPORT的收資料是由線程完成的。相應線程類是:TcomThread;因此,決定看看線程優先順序。哦,是tpNormal.那調高這個優先順序會不會有所改善?改成tohigher,tphighest…問題依然!看來與線程優先順序無關。再仔細研究這個線程的代碼, TComThread = class(TThread) private    FComPort: TCustomComPort;    FStopEvent: THandle;    FEvents: TComEvents; protected    procedure DispatchComMsg;    procedure DoEvents;    procedure Execute; override;    procedure SendEvents;    procedure Stop; public    constructor Create(AComPort: TCustomComPort);    destructor Destroy; override; end; 從Execute入口,得知:線程內部是利用了系統事件對象完成對串口資料接收的觸發。當收到事件後,把系統對應的事件儲存在組合的屬性中。    TComEvent = (evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR,    evError, evRLSD, evRx80Full); TComEvents = set of TComEvent;     // if event occurs, dispatch it    if (Signaled = WAIT_OBJECT_0 + 1)      and GetOverlappedResult(FComPort.Handle, Overlapped, BytesTrans, False)    then    begin//      FEvents := IntToEvents(Mask);      DispatchComMsg;    end; 從藍色的代碼可知:當發生串口事件時,儲存事件類型,然後就分發事件,找對應的事件來執行這個接收過程了。於是再看DispatchComMsg方法:// dispatch eventsprocedure TComThread.DispatchComMsg;begin case FComPort.SyncMethod of    smThreadSync: Synchronize(DoEvents); // call events in main thread    smWindowSync: SendEvents; // call events in thread that opened the port    smNone:       DoEvents; // call events inside monitoring thread end;end; 在doEvents這個同步方法中,無法執行相應的事件。從注釋來看,是指在主線程中執行這個操作,由於此時是封裝在DLL中,沒有主線程存在,因此,這個方法的執行也就是石沉大海了。這就是無法接收資料的原因了。 而第二個項就是:調用開啟串口的線程對應事件。看來這個有戲。因此,將組件線程的同步方法類型改成 smWindowSync 果然,接收資料正常。 對於第三個選項:在監視線程中執行事件,本人沒有測試,因為時間關係。。。。。哎,有興趣的DELPHIER可以試試。。。。。。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.