2008-08-28 96 views
39

好吧,我有一個奇怪的異常從我的代碼引發了很多年來一直困擾着我。WSACancelBlocking呼叫異常

System.Net.Sockets.SocketException: A blocking operation was interrupted by a call to WSACancelBlockingCall 
    at System.Net.Sockets.Socket.Accept() 
    at System.Net.Sockets.TcpListener.AcceptTcpClient() 

MSDN是不會在這個非常有幫助:http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx,我甚至不知道如何開始解決此一個。它每天只能投擲4到5次,從不在我們的測試環境中。只在生產現場和所有生產現場。

我發現大量的帖子詢問這個異常,但沒有真正的明確答案是什麼導致它,以及如何處理或防止它。

的代碼運行在一個獨立的後臺線程,方法開始:

public virtual void Startup() 
    { 
    TcpListener serverSocket= new TcpListener(new IPEndPoint(bindAddress, port));  
     serverSocket.Start(); 

然後我運行一個循環將作爲作業的所有新連接在一個單獨的線程池。它變得更加複雜,因爲應用程序架構,但基本上:

while ((socket = serverSocket.AcceptTcpClient()) !=null) //Funny exception here 
    { 
     connectionHandler = new ConnectionHandler(socket, mappingStrategy); 
     pool.AddJob(connectionHandler); 
    } 
    } 

從那裏,pool有它自己的線程照顧每個作業的在它自己的線程,分別。

我的理解是,AcceptTcpClient()是一個阻塞調用,並以某種方式winsock告訴線程停止阻塞並繼續執行..但爲什麼?我該怎麼做?只要趕上例外並忽略它呢?


嗯,我確實認爲其他線程正在關閉套接字,但它肯定不是來自我的代碼。 我想知道的是:此套接字是由連接客戶端(在套接字的另一側)關閉還是由我的服務器關閉?因爲就像現在一樣,無論何時發生這種異常,它都會關閉我的監聽端口,從而有效地關閉我的服務。如果這是從遠程位置完成的,那麼這是一個主要問題。

另外,這可能是簡單的IIS服務器關閉我的應用程序,從而取消我的所有後臺線程和阻止方法?

回答

35

是否有可能從另一個線程關閉serverSocket?這將導致這種異常。

+0

說吧。你如何從另一個線程關閉它?套接字是否需要「易失性」? – 2011-03-26 21:21:31

4

這可能發生在serverSocket.Stop()上。當我調用Dispose時,我打了電話。

這裏是我的監聽線程的異常處理怎麼看起來像:

try 
{ 
    //... 
} 
catch (SocketException socketEx) 
{  
    if (_disposed) 
     ar.SetAsCompleted(null, false); //exception because listener stopped (disposed), ignore exception 
    else 
     ar.SetAsCompleted(socketEx, false); 
} 

現在發生了什麼事,之前_disposed設置爲true會出現每隔一段時間例外。所以對我來說,解決方案是讓所有線程都安全。

3

同一個! 但我想通了,'服務器端'的ReceiveBuffer被客戶端淹沒了! (在我的情況下,一羣RFID掃描器,不斷髮送TagCode,而不是停止發送,直到下一個TagCode到達)

它有助於提高ReceiveBuffers並重新配置掃描器...

5

這是我的示例解決方案,以避免WSAcancelblablabla: 定義您的主題全球那麼你可以使用invoke方法是這樣的:

private void closinginvoker(string dummy) 
    { 
     if (InvokeRequired) 
     { 
      this.Invoke(new Action<string>(closinginvoker), new object[] { dummy }); 
      return; 
     } 
     t_listen.Abort(); 
     client_flag = true; 
     c_idle.Close(); 
     listener1.Stop(); 
    } 

你調用它之後,首先關閉線程則永遠循環標誌等等它會阻止進一步的等待(如果有的話),然後關閉tcpclient然後停止偵聽器。

相關問題