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

TThread 呼叫 NMFTP元件時的問題?

尚未結案
kuochih
一般會員


發表:2
回覆:8
積分:2
註冊:2003-07-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-06-28 15:53:54 IP:163.28.xxx.xxx 未訂閱
各位大大好:    程式需求: 我需要定期執行一段函式, 在此 我選擇了TThread來完成定期呼叫這件工作。    函式之中, 我需要定期下載ftp的文件, 我選擇了 元件NMFTP來完成 ftp client。    程式基本函式: void ftpdownload(void);                //利用NMFTP完成ftp client Button1Click                         //執行ftpdownload(); Butoon2Click                         //執行Thead TtestThread::Execute()                 //執行ftpdownload();   問題描述: 當我按下 Button1時, 可成功下載ftp上的文件, 可是當我按下Button2時, 我利用BCB dubug功能,  F7 顯示程式碼會停在 NMFTP1->Download(); 這一行。 沒看到error message, 程式也沒當掉。        底下是我的寫了一段測試code    //unit1.cpp  begin========================================================================================= //---------------------------------------------------------------------------    #include  #pragma hdrstop #include "Unit1.h" #include "Unit2.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ftpdownload(); ShowMessage("download ok!"); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { testThread = new TtestThread(true); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { AnsiString f = ".//logOfTcpdumpTx0.txt" ; DeleteFile(f.c_str()); testThread -> Resume(); } //--------------------------------------------------------------------------- void TForm1::ftpdownload(void) { NMFTP1->Host="140.115.xxx.xxx"; NMFTP1->"kuochih"; NMFTP1->Password="xxxxxx"; NMFTP1->Connect(); //$cd /home/kuochih/myLog NMFTP1->ChangeDir("/home/kuochih/myLog"); NMFTP1->Download("logOfTcpdumpTx0.txt", "logOfTcpdumpTx0.txt"); //停再這一行 NMFTP1->Disconnect(); } //unit1.cpp end=========================================================================================== //unit2.cpp begin========================================================================================= //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #pragma package(smart_init) //--------------------------------------------------------------------------- // Important: Methods and properties of objects in VCL can only be // used in a method called using Synchronize, for example: // // Synchronize(UpdateCaption); // // where UpdateCaption could look like: // // void __fastcall TtestThread::UpdateCaption() // { // Form1->Caption = "Updated in a thread"; // } //--------------------------------------------------------------------------- __fastcall TtestThread::TtestThread(bool CreateSuspended) : TThread(CreateSuspended) { } //--------------------------------------------------------------------------- void TtestThread::SetName() { THREADNAME_INFO info; info.dwType = 0x1000; info.szName = "testThread"; info.dwThreadID = -1; info.dwFlags = 0; __try { RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info ); } __except (EXCEPTION_CONTINUE_EXECUTION) { } } //--------------------------------------------------------------------------- void __fastcall TtestThread::Execute() { SetName(); //---- Place thread code here ---- Sleep(1000); Form1->Edit1->Text = "thread begin"; Sleep(1000); Form1->Edit1->Text = ""; while(1) { Form1->ftpdownload(); Sleep(10000); } } //--------------------------------------------------------------------------- //unit2.cpp begin========================================================================================= 在PO此問題之前, 我曾經在本站搜尋過TThread相關文章 看到 http://delphi.ktop.com.tw/topic.php?topic_id=46355 RaynorPao 大大曾提 (1)不建議這樣子做,那是不安全的,因為 VCL 並不是 Thread Safe 的,而ShowMessage 也是 VCL 的一部分 所以我在猜想, 會不會是同原因, TThread不適合呼叫VCL元件? 由於不確定原因, 所以將問題PO上來, 希望版上大大能給我ㄧ些建議, 要怎麼做才能改善我目前遇到的問題? 謝謝!
kuochih
一般會員


發表:2
回覆:8
積分:2
註冊:2003-07-17

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-06-29 05:01:15 IP:163.28.xxx.xxx 未訂閱
各位大大好, 問題已獲得解決, 只要將ftpdownload(); synchronize()即可解決問題。 心得:即使只有單一thread 執行VCL元件,仍建議使用syncronize(); ShowMessage();也可由同樣的方法解決。 修改部分程式碼如下: //修改的部份 begin=========================================== void __fastcall TtestThread::Execute() { SetName(); //---- Place thread code here ---- Sleep(1000); Form1->Edit1->Text = "thread begin"; Sleep(1000); Form1->Edit1->Text = ""; while(1) { Synchronize(kkk); Sleep(2000); } //Form1->ftpdownload(); } //--------------------------------------------------------------------------- void __fastcall TtestThread::kkk() { Form1->ftpdownload(); } //修改的部份 end==============================================
powerhowardchen
初階會員


發表:15
回覆:28
積分:28
註冊:2004-04-19

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-07-01 12:25:41 IP:61.70.xxx.xxx 未訂閱
我最近經常在寫TThread的程式, 提供ㄧ點經驗給你參考. 使用 Thread 元件時, 儘量堅守 a.Thread內所使用的元件、資源或是記憶體空間, 儘量均於Thread內建立與釋放 b.同上, 所以儘量不要使用共用變數或是靜態變數, 除非你確定它不會造成資源重用 b.於Thread建立時, 即給定任務, 或是以Synchronize()、Signal()、Mutex()、Windows Message等給定任務或做訊息同步 c.密切注意是否有資源重複使用的問題 Synchronize(), 是用於Thread間同步, 使用Synchronize時, 是依然會佔用MainThread的時間的, 用Synchronize的話, 就跟沒有寫Thread是一樣的, 只是花了力氣建了一個傀儡Thread, 而MainThread在執行ftpdownload()的同時, 卻依然不能做其他事情. 而且, 看你後來的寫法, 在Execute()裡用了 Sleep(1000); Form1->Edit1->Text = "thread begin"; Sleep(1000); Form1->Edit1->Text = ""; 這樣是很危險的, 因為Form1還是MainThread的資源, 可能會因為搶到而發生錯誤. 建議應該是用以下寫法: __fastcall TtestThread::TtestThread(string AHost, string AUserID, string APassword, string ARemotePath, string AFileName) : TThread(false) { mHost = AHost; mUserID = AUserID; mPassword = APassword; mRemotePath = ARemotePath; mFileName = AFileName; mDisplayState = ""; } //--------------------------------------------------------------------------- void __fastcall TtestThread::DoDisplayState() { Form1->Edit1->Text = mDisplayState; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TtestThread::ftpdownload() { __try { TNMFTP *NMFTP1 = new TNMFTP(null); __try { mDisplayState = "FTP Synchronize Begin..."; Synchronize(DoDisplayState); NMFTP1->Host=mHost; NMFTP1->mUserID; NMFTP1->Password=mPassword; NMFTP1->Connect(); //$cd /home/kuochih/myLog NMFTP1->ChangeDir(ARemotePath); NMFTP1->Download(AFileName, AFileName); NMFTP1->Disconnect(); mDisplayState = "FTP Synchronize Success."; Synchronize(DoDisplayState); } __finally { delete NMFTP1; } } __except (Exception e) { mDisplayState = "FTP Synchronize Fail: " e->ClassName ":" e->Message; Synchronize(DoDisplayState); } } //--------------------------------------------------------------------------- void TtestThread::SetName() { THREADNAME_INFO info; info.dwType = 0x1000; info.szName = "testThread"; info.dwThreadID = -1; info.dwFlags = 0; __try { RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info ); } __except (EXCEPTION_CONTINUE_EXECUTION) { } } //--------------------------------------------------------------------------- void __fastcall TtestThread::Execute() { SetName(); //---- Place thread code here ---- Sleep(1000); mDisplayState = "thread begin"; Synchronize(DoDisplayState); Sleep(1000); mDisplayState = ""; Synchronize(DoDisplayState); while(!Terminated) { ftpdownload(); Sleep(10000); } } PS. Sorry! 因為我是Delphi的慣用者, 另外就常用VC , C Builder很少用, C Builder的ㄧ些變數用法我可能用錯了, 您就將就的看一下. 還有, 建議你用Indy的元件, 必較沒問題, 很好用, 不像NMHTTP, 老是發生怪事. Howard Chen. Delphi, Java 我的神..... .NET 垃圾筒在哪裡?...
kuochih
一般會員


發表:2
回覆:8
積分:2
註冊:2003-07-17

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-07-05 15:08:21 IP:163.28.xxx.xxx 未訂閱
謝謝 powerhowardchen 寶貴的意見。
系統時間:2024-11-22 8:39:05
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!