線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2980
推到 Plurk!
推到 Facebook!

Indy TCPServer 與 DataModule->ClinentDataSet->DataRequest()問題

答題得分者是:aftcast
shchen
一般會員


發表:12
回覆:26
積分:7
註冊:2003-08-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-03-26 21:28:50 IP:116.6.xxx.xxx 訂閱
各位前輩們,小弟是用BCB,不得已在此發文求助了.
小弟做了一套MIDAS架構的資料庫系統,在上線使用一段時間了,現在遇到了需要讓其它程式設計師能與我做的Client端程式溝通操作取得資料,所以我選用了TIdTCPServer/Client 元件,在本地建立了Socket連線,讓對方的程式與我的三層架構中的Client程式交談,主要是對傳TStream 型態資料.
目前Socket 溝通及資料回傳都成功做好了,但遇到一個問題,就是在TIdTCPServer.OnExecute()事件內對於要做遠端資料查詢的動作時,就會出現
EOleException with message "CoInitialize 尚未被呼叫"的問題,如下:

void __fastcall TMainForm::IdTCPServer1Execute(TIdContext *AContext)
{
int Result=DataModule1->ClientDataSet1->DataRequest(""); -->報錯 "CoInitialize 尚未被呼叫"
if(Result==0)
......
}

若是加上CoInitialize(NULL); 又變成EOleException with message "應用程式所呼叫了整理給不同執行緒的介面"
void __fastcall TMainForm::IdTCPServer1Execute(TIdContext *AContext)
{
CoInitialize(NULL);
int Result=DataModule1->ClientDataSet1->DataRequest(""); -->報錯 "應用程式所呼叫了整理給不同執行緒的介面"
if(Result==0)
......
CoUninitialize();
}
經過了詳細測試,已經可以確定,只要是在TIdTCPServer,觸發的事件中,調用DataModule1內的ClientDataSet物件,就會產生這問題,真不知道該怎麼解決唉...灰心,要重寫了,
是Colinitialize()加錯地方嗎,有誰遇過相同問題...求助..
我的TCPServer IP是用127.0.0.1,port是設8090.


編輯記錄
shchen 重新編輯於 2011-03-26 07:33:28, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-03-27 12:06:06 IP:111.249.xxx.xxx 未訂閱
是的,你加錯地方了

主要原因是 TCPServer的 Connection, Execute, Disconnection三個事件(請自行加on)
是給Client Thread,不是給執行程式的Main Thread,你這樣做會有兩個問題

一、存取區域的問題,你的DataModule不在你的事件中,存取到null
二、ClientDataSet不是Thread Safe物件,與Main Thread搶,它當然要殺人了

結論仍然是Thread Safe衍生的狀況
解決的辦法可以用兩種

一、用SendMessage去呼叫DataModule
二、用TIdSync物件去Synchronize VCL處理

以上
編輯記錄
GrandRURU 重新編輯於 2011-03-26 22:16:31, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-03-28 20:40:41 IP:220.135.xxx.xxx 訂閱
發現你的語法是bcb吧?  這裡好像是delphi…


不過我建議要不要先試一下:

void __fastcall TMainForm::IdTCPServer1Execute(TIdContext *AContext)
{
CoInitialize(NULL); //保留
TDataModule1 *m1 = new TDataModule1(0);
__try
{
m1-> 有的沒的設定 (因為是新建的,所以可能有些初始之類的,看情形
int Result=m1->ClientDataSet1->DataRequest(""); -->報錯 "應用程式所呼叫了整理給不同執行緒的介面"
if(Result==0)
......
}
__fianlly
{
delete m1;
}
CoUninitialize(); //保留

}

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
taishyang
站務副站長


發表:377
回覆:5486
積分:4552
註冊:2002-10-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-03-29 10:00:39 IP:122.116.xxx.xxx 訂閱
幫忙移區 ^^
shchen
一般會員


發表:12
回覆:26
積分:7
註冊:2003-08-13

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-04-02 10:57:52 IP:116.6.xxx.xxx 訂閱
沒錯,我最後也是用與你樣同的方式而成功,因為本人對的Class概念的基礎不夠,對於瞎摸試出來的方式,不知道對不對,現有你的回覆,知道方法正確的.
另外看文件,也體會,TId物件都是獨立thread的物件,不能直接呼叫主thread內的物件.

===================引 用 aftcast 文 章===================
發現你的語法是bcb吧? 這裡好像是delphi…


不過我建議要不要先試一下:

void __fastcall TMainForm::IdTCPServer1Execute(TIdContext *AContext)
{
CoInitialize(NULL); //保留
TDataModule1 *m1 = new TDataModule1(0);
__try
{
m1-> 有的沒的設定 (因為是新建的,所以可能有些初始之類的,看情形
int Result=m1->ClientDataSet1->DataRequest(""); -->報錯 "應用程式所呼叫了整理給不同執行緒的介面"
if(Result==0)
......
}
__fianlly
{
delete m1;
}
CoUninitialize(); //保留

}

shchen
一般會員


發表:12
回覆:26
積分:7
註冊:2003-08-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-04-02 11:03:02 IP:116.6.xxx.xxx 訂閱
感謝回覆,兩位大哥,一位說明了準確問題原因,一位給了標準答案,
===================引 用 GrandRURU 文 章===================
是的,你加錯地方了
shchen
一般會員


發表:12
回覆:26
積分:7
註冊:2003-08-13

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-04-02 11:10:13 IP:116.6.xxx.xxx 訂閱
不好意思,給您添煩麻了,
建議版主能不能在C Builder區內加個多層式架構的版,或將此版的版名加上"與多層式架構",例如網際網路程式與多層式架構(Muilt-tir)設計討論區(C Builder)

===================引 用 taishyang 文 章===================
幫忙移區 ^^
系統時間:2017-12-19 2:22:37
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!