lkkplayer
一般會員

 發表:26 回覆:59 積分:17 註冊:2006-11-22
發送簡訊給我
|
請教各位,我是用Delphi7 我有使用TCPCLIENT 但是很奇怪每次程式執行後,要離開時都會錯誤, 我要離開的時候會執行下面程式碼 var Client : TIdTCPClient; . . . if Client <> nil then if Client.Connected then Client.Disconnect; 不知道我離開時執行這段程式碼是不是斷線不完全,導致有錯誤的視窗。 錯誤視窗如附件。 請教各位有遇過這種情況嗎?
編輯記錄
lkkplayer 重新編輯於 2008-07-21 18:28:12, 註解 無‧
|
careychen
尊榮會員
    
 發表:41 回覆:580 積分:959 註冊:2004-03-03
發送簡訊給我
|
大大的問題,小弟試的時候是不會,但我是用 indy 10 的,不知道有沒有差 或是您可以 Po 部份的程式碼來看看是不是您中間有寫了什麼造成這段訊息的出現??
------ 價值的展現,來自於你用哪一個角度來看待它!!
|
lkkplayer
一般會員

 發表:26 回覆:59 積分:17 註冊:2006-11-22
發送簡訊給我
|
附上程式碼.... [code delphi] procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); begin if MessageDlg('要離開系統?',mtConfirmation,[mbYes,mbNo],0)=mrYes then begin LogOut; Action := caFree end else Action := caNone; end; procedure TfrmMain.LogOut; begin if adDBConn.Connected then begin // 更新DB.Users.loggedin (登入狀態1-->0) adCmd.Connection := frmMain.adDBConn; adCmd.CommandText:= 'update users set loggedin=0' ' where username=''' UserInfo.Username ''''; adCmd.Execute; end; // if ClientHandleThread <> nil then ClientHandleThread.Terminate; if Client <> nil then if Client.Connected then Client.Disconnect; // tmAutoConnSvr.Enabled := False; tmShowStatus.Enabled := False; end; procedure TfrmMain.tmAutoConnSvrTimer(Sender: TObject); var i : integer; Temp : TComponent; strMsg : string; begin strMsg := ''; // ShowMsg('正主動重新連線到 Sever ...'); // Keep at window for i := 0 to Componentcount - 1 do begin Temp := Components[i]; if (Temp is TForm) then begin with TForm(FindComponent(Temp.Name)) do begin if (Name <> 'frmMain') and Showing then close; end; end; end; // Set ClientHandleThread to if (Sender AS TTimer).Tag = 0 then begin if ClientHandleThread.Terminated then begin ClientHandleThread := nil; (Sender AS TTimer).Tag := (Sender AS TTimer).Tag 1; end; end; // try to connect Server if (Sender AS TTimer).Tag = 1 then begin // try FreeAndNil(Client); Client := TIdTCPClient.Create(frmMain); Client.Host := Login.SVR; Client.Port := 24451; Client.Connect(1000); // (Sender AS TTimer).Tag := (Sender AS TTimer).Tag 1; ShowMsg('重新連線到 Server 成功。'); except on E : exception do begin plCenter.Color := clRed; strMsg := '重新連線到 Server 失敗。'; end; end; // ShowMsg(strMsg); StatusBar.Panels[4].Text := strMsg; end; // Re-Connect DB & Re-Create ClientHandleThread if (Sender AS TTimer).Tag = 2 then begin // 若 Client 至 Server 之間的網路線路有問題 (例如:突然拔掉 Client 網路線) // adDBConn 的連線狀態雖然仍保持 "TRUE",但實際用 [netstat] 觀測已經失效 if adDBConn.Connected then adDBConn.Close; // try adDBConn.Open; if adDBConn.Connected then ShowMsg('重新連線到本機資料庫成功。'); // ClientHandleThread := TClientHandleThread.Create(True); ClientHandleThread.FreeOnTerminate:=True; ClientHandleThread.Priority := tpLower; ClientHandleThread.Resume; // (Sender AS TTimer).Tag := (Sender AS TTimer).Tag 1; except on E: Exception do begin plCenter.Color := clRed; strMsg := '重新連線到本機資料庫失敗。'; end; end; // plCenter.Color := clSkyBlue; strMsg := 'Stop Timer.'; ShowMsg(strMsg); StatusBar.Panels[4].Text := strMsg; // (Sender AS TTimer).Enabled := False; (Sender AS TTimer).Interval:= 2000; (Sender AS TTimer).Tag:=0; end; end;
procedure TfrmMain.tmShowStatusTimer(Sender: TObject); var blCheck : boolean; strMsg : string; begin if ClientHandleThread = nil then StatusBar.Panels[4].Text := 'ClientHandleThread is nil'; blCheck := False; StatusBar.Panels[1].Text := FormatDateTime('yyyy/mm/dd HH:nn:ss', now); // 每天固定時段->檢查資料庫 乙次 if DEFAULT_Prompt_Tm <> '' then begin strMsg := DEFAULT_Prompt_Tm ' <==> ' FormatDateTime('HH:nn:ss',Time); if DEFAULT_Prompt_Tm = FormatDateTime('HH:nn:ss',Time) then begin blCheck := True; strMsg := strMsg '.....BINGO!!'; end; //test //ShowMsg(strMsg); end else if (SecondOf(now)=0) and (MinuteOf(now)=0) and (HourOf(now)=9) then blCheck := True; if blCheck then begin btnChkInformClick(Self); end; end; [/code]
===================引 用 careychen 文 章=================== 大大的問題,小弟試的時候是不會,但我是用 indy 10 的,不知道有沒有差 或是您可以 Po 部份的程式碼來看看是不是您中間有寫了什麼造成這段訊息的出現??
編輯記錄
lkkplayer 重新編輯於 2008-07-20 08:45:25, 註解 無‧
|
careychen
尊榮會員
    
 發表:41 回覆:580 積分:959 註冊:2004-03-03
發送簡訊給我
|
看了您的程式碼,建議你查一下 ClientHandleThread , 因為這個雖然對他下了 Terminate, 但他如果是被用來一直讀 Server 傳來的訊息,那實際上這個 Thread 是沒有停止的哦~~! 我假設你的 ClientHandleThread 的 OnExecute 的寫法是這樣
[code delphi] procedure TClientHandleThread.OnExecute; begin while Not Client.Disconnected do begin // Indy 10 的語法, 了解小弟的意思就行 // 那這個 Thread 其實是卡在這邊一直在等著由 Server 傳來的訊息 // 所以雖然下了 Terimate ,但【還是卡在這裡哦!!】 Data := Client.IOHandler.ReadLn; Synchronize(HandleFunctionName); end; end; [/code]
當最後你對他下了
if ClientHandleThread <> nil then ClientHandleThread.Terminate; <== 只是標記要結束,但未真正結束 if Client <> nil then if Client.Connected then Client.Disconnect; <== 但這行一執行後,引發 Thread 內等著 ReadLn 的指令錯誤
你先查看看是不是因為如此造成的
------ 價值的展現,來自於你用哪一個角度來看待它!!
|
lkkplayer
一般會員

 發表:26 回覆:59 積分:17 註冊:2006-11-22
發送簡訊給我
|
我的程式碼如下:這樣寫會有問題嗎? [code delphi] procedure TClientHandleThread.Execute; begin while not Terminated do begin if not Client.Connected then Terminate else try Client.ReadBuffer(CB, Sizeof(CB)); Synchronize(HandleInput); except on E:Exception do begin // ShowMsg('ClientHandleThread Excute Error ::' E.Message); if Client.Connected then Client.Disconnect; frmMain.tmAutoConnSvr.Enabled := True; end; end; end; end; [/code]
|
careychen
尊榮會員
    
 發表:41 回覆:580 積分:959 註冊:2004-03-03
發送簡訊給我
|
平常你可以觀察一下,程式應該是一直停在 Client.ReadBuffer(CB, Sizeof(CB)); 這一行,除非有訊息進來,否則他是不會動的,所以你下 Termiate 時, 他還是會停在那一行,但後來下了 Disconnect 時,他會觸發這一行的錯誤, 因為你現在是 Design mode 所以會看到這個訊息, 但是因為你有寫 try...except.. end 所以你在 RunTime Mode 時, 應該是看不到這行錯誤的,程式會正常的關閉,對嗎? 要測試的話,在你的 Main form 上放一個 button ,按下 Click 後,裡面寫 Client.Disconnect; 你看一下引發的訊息是不是一樣的 ===================引 用 lkkplayer 文 章=================== 我的程式碼如下:這樣寫會有問題嗎? [code delphi] procedure TClientHandleThread.Execute; begin while not Terminated do begin if not Client.Connected then Terminate else try Client.ReadBuffer(CB, Sizeof(CB)); //< == 你可以看看是不是在這邊 Waiting Synchronize(HandleInput); except on E:Exception do begin // ShowMsg('ClientHandleThread Excute Error ::' E.Message); if Client.Connected then Client.Disconnect; frmMain.tmAutoConnSvr.Enabled := True; end; end; end; end;[/code]
------ 價值的展現,來自於你用哪一個角度來看待它!!
|
lkkplayer
一般會員

 發表:26 回覆:59 積分:17 註冊:2006-11-22
發送簡訊給我
|
careychen大大: 我依照你說的測試方法,Main form 上放一個 button ,按下 Click 後,裡面寫 Client.Disconnect; 在偵錯模式下,就會出現那個錯誤訊息,不知道是不是因為這個樣子 導致我直接執行程式檔時,然後離開,蠻常會出現那種程式發生問題,叫我關閉, 問我是否回報此問題或不回報微軟的確認視窗,這個問題有方法解決嗎? ===================引 用 careychen 文 章=================== 平常你可以觀察一下,程式應該是一直停在 Client.ReadBuffer(CB, Sizeof(CB)); 這一行,除非有訊息進來,否則他是不會動的,所以你下 Termiate 時, 他還是會停在那一行,但後來下了 Disconnect 時,他會觸發這一行的錯誤, 因為你現在是 Design mode 所以會看到這個訊息, 但是因為你有寫 try...except.. end 所以你在 RunTime Mode 時, 應該是看不到這行錯誤的,程式會正常的關閉,對嗎? 要測試的話,在你的 Main form 上放一個 button ,按下 Click 後,裡面寫 Client.Disconnect; 你看一下引發的訊息是不是一樣的 ===================引 用 lkkplayer 文 章=================== 我的程式碼如下:這樣寫會有問題嗎? [code delphi] procedure TClientHandleThread.Execute; begin while not Terminated do begin if not Client.Connected then Terminate else try Client.ReadBuffer(CB, Sizeof(CB)); //< == 你可以看看是不是在這邊 Waiting Synchronize(HandleInput); except on E:Exception do begin // ShowMsg('ClientHandleThread Excute Error ::' E.Message); if Client.Connected then Client.Disconnect; frmMain.tmAutoConnSvr.Enabled := True; end; end; end; end;[/code]
|
careychen
尊榮會員
    
 發表:41 回覆:580 積分:959 註冊:2004-03-03
發送簡訊給我
|
你改像下面這樣試試,不過看你的程式碼似乎是用 Indy9 的,我現在是用 Indy 10 的 不知道會不會有差別,至少我現在是這樣用的,在 Indy 10 上沒有出現錯誤訊息
[code delphi] procedure TClientHandleThread.Execute; begin try // 多加一層 Try Except while not Terminated do begin if not Client.Connected then Terminate else try Client.ReadBuffer(CB, Sizeof(CB)); Synchronize(HandleInput); except on E:Exception do begin // 下面這行 Showmsg 取消 //ShowMsg('ClientHandleThread Excute Error ::' E.Message); if Client.Connected then Client.Disconnect; frmMain.tmAutoConnSvr.Enabled := True; end; end; end; except Self.Terminate; end; end; [/code]
------ 價值的展現,來自於你用哪一個角度來看待它!!
|
lkkplayer
一般會員

 發表:26 回覆:59 積分:17 註冊:2006-11-22
發送簡訊給我
|
careychen大大: 試用你的方法,似乎已經不會再出現錯誤訊息了,持續觀察中。 感謝你^^"。 另外想請教你一件事,有沒有啥書或者文件網站之類的有講多執行緒與工作排程 多執行緒的控制權轉移真的非常難搞>"< ===================引 用 careychen 文 章=================== 你改像下面這樣試試,不過看你的程式碼似乎是用 Indy9 的,我現在是用 Indy 10 的 不知道會不會有差別,至少我現在是這樣用的,在 Indy 10 上沒有出現錯誤訊息 [code delphi] procedure TClientHandleThread.Execute; begin try // 多加一層 Try Except while not Terminated do begin if not Client.Connected then Terminate else try Client.ReadBuffer(CB, Sizeof(CB)); Synchronize(HandleInput); except on E:Exception do begin // 下面這行 Showmsg 取消 //ShowMsg('ClientHandleThread Excute Error ::' E.Message); if Client.Connected then Client.Disconnect; frmMain.tmAutoConnSvr.Enabled := True; end; end; end; except Self.Terminate; end; end; [/code]
|
careychen
尊榮會員
    
 發表:41 回覆:580 積分:959 註冊:2004-03-03
發送簡訊給我
|
呵,不客氣能夠解決你的問題才是最重要的 另~~~ 你說的書籍和資料,我還沒買過這方面的書籍,其實我大部份都是在下面這三個地方找到答案 1、KTop 2、大陸的 CSDN 3、Google (其實大部份的解答還是指向1 和 2) 不過,你要找有 Thread 的相關東東,找找 CriticalSection 這個關鍵字 有些文章提到這個名詞時會對 Thread 有一些解釋,會增加你對 Thread 的觀念
或是 Indy 的 IdThreadComponent 他是直接實作 TThread 變成一個元件也可以參考看看
------ 價值的展現,來自於你用哪一個角度來看待它!!
|