在 Indy TIdTCPServer 和 TIdTCPClient 中管理例外
我在本論壇的其他帖子和其他地方都讀到過,在 Indy 組件中,例外(從EIdException)是內部管理的。為此,在 TCPServerExecute方法中不需要使用try - catch塊。但是如果在 TCPServerExecute方法中發生另一種例外會發生什么?
在我的服務器應用程式中,我TIdTCPServer在主表單上放置了一個組件,如果它的Execute方法內部發生了不好的事情并且我不管理它,服務器就會停止。顯然我需要運行服務器,所以我使用一個try - catch塊,如果有例外(任何型別的例外),我重新啟動服務器。我不知道這是否是最好的做法。
有時,在 IDE 中運行服務器應用程式時,出現錯誤
Project CallMonitor.exe raised exception class EIdSocketError with message 'Socket Error # 10054 - Connection reset by peer.'.
可能是由在同一臺計算機上運行的客戶端(不在 IDE 中)引起的。應用程式執行被阻止,如果我中斷,代碼會在 IdStack 檔案中停止,那里有大的自述!!!關于例外 10038。我按 F9,應用程式繼續運行。
對我來說,不太清楚會發生什么。我的try - catch塊在這種情況下有效嗎?或者它是無用的還是有害的?我必須過濾 Indy 例外和其他例外?
在客戶端,在我的應用程式中,主表單中有一個 TIdTCPClient 物件,與服務器的連接在主執行緒中進行管理。然后還有另一個執行緒來管理與服務器的通信。在通信執行緒Execute方法中,我有一個try - catch塊和一個回圈,在該回圈中我每 2 秒或當用戶請求資料時向服務器發送一個請求,然后我對服務器的回答進行解碼。如果有EIdReadTimeout例外,我終止執行緒并重新啟動它。對于其他例外,我終止執行緒,斷開/連接 TIdTCPClient 并重新啟動執行緒。
我認為這是一種不同的情況,因為在服務器中,例外是在 TIdTCPServer 執行緒內管理的,而在客戶端中,例外是在僅使用TCPClient->Socket與服務器通信的執行緒中管理的,對嗎?
任何答案/評論/建議表示贊賞。
uj5u.com熱心網友回復:
在 TCPServer
Execute方法中,不需要使用try - catch塊。但是如果在 TCPServerExecute方法中發生另一種例外會發生什么?
任何允許從OnConnect或OnExecute事件回傳的未捕獲例外都TIdTCPServer將導致呼叫TIdContext執行緒停止運行。它將Connection在清理期間關閉其關聯的客戶端,從而觸發OnDisconnect事件。然后OnException事件將在之后被觸發。
在我的服務器應用程式中,我
TIdTCPServer在主表單上放置了一個組件,如果它的Execute方法內部發生了不好的事情并且我不管理它,服務器就會停止。
服務器作為一個整體不會停止。只有呼叫TIdContext執行緒被停止。
顯然我需要運行服務器,所以我使用一個
try - catch塊,如果有例外(任何型別的例外),我重新啟動服務器。
沒有必要在任何例外情況下重新啟動整個服務器。僅適用于使您的應用程式正常運行所需的某些內容無效/損壞的例外。
有時,在 IDE 中運行服務器應用程式時,出現錯誤
Project CallMonitor.exe raised exception class EIdSocketError with message 'Socket Error # 10054 - Connection reset by peer.'.
這是一個完全正常的套接字錯誤。那不會殺死您的整個服務器。
如果您進入 IDE 的除錯器設定,則可以選擇忽略 Indy“靜默”例外(源自EIdSilentException,例如EIdConnClosedGracefully)。或者,您也可以告訴除錯器要忽略的特定例外型別,例如EIdSocketError.
應用程式執行被阻止...我按 F9 并且應用程式繼續運行。
確切地。不是致命錯誤。阻塞僅在除錯器中,它讓您檢查例外并決定如何處理它。
對我來說,不太清楚會發生什么。我的
try - catch塊在這種情況下有效嗎?
IDE 除錯器會先于您的代碼捕獲例外。當您按下F9繼續執行時,例外將被傳遞回您的代碼,適當的catch將正常處理它。
或者它是無用的還是有害的?
不。
我必須過濾 Indy 例外和其他例外?
如果您完全捕獲例外,請處理您需要的例外,然后您應該重新拋出您捕獲的任何 Indy 特定的例外(所有 Indy 例外都源自于EIdException以便于識別),讓服務器處理它們。如果不這樣做,那么您應該Connection自己斷開呼叫并優雅地退出事件處理程式。無論哪種方式,服務器都會根據需要清理其余部分。
在客戶端,在我的應用程式
TIdTCPClient中,主表單中有一個物件,與服務器的連接在主執行緒中進行管理。然后還有另一個執行緒來管理與服務器的通信。
我也會將連接管理移動到作業執行緒中。如果需要,連接、通信、斷開連接、重復,都應該在一個執行緒中。
在通信執行緒
Execute方法中,我有一個try - catch塊和一個回圈,在該回圈中我每 2 秒或當用戶請求資料時向服務器發送一個請求,然后我對服務器的回答進行解碼。如果有EIdReadTimeout例外,我終止執行緒并重新啟動它。
如果實際讀取操作超時,則通信狀態未知且可能無法恢復,因為您不知道哪個位元組是超時的位元組。因此,您應該斷開連接并重新連接,而不僅僅是重新啟動執行緒。唯一不需要完全重新連接的時間是,如果您正在處理訊息之間的超時等待,并且知道通信沒有損壞。在這種情況下,在沒有完全重新連接的情況下簡單地重新啟動執行緒不太可能解決超時情況。再次重試等待操作會更簡單。
對于其他例外,我終止執行緒,斷開/連接
TIdTCPClient并重新啟動執行緒。
如果連接/斷開邏輯被移到執行緒中,它們可以在一個回圈中完成,那么就不需要重新啟動執行緒本身。創建/銷毀執行緒的成本很高(從作業系統的角度來看),因此盡可能重用執行緒。
我認為這是一種不同的情況,因為在服務器中,例外是在
TIdTCPServer執行緒內部管理的,而在客戶端中,例外是在一個僅使用TCPClient->Socket與服務器通信的執行緒中管理的,對嗎?
是的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/390999.html
標籤:例外 时间:2019-05-06 标签:c builder 印地10
上一篇:發生例外時如何重復代碼?[復制]
