52

わかりました、コードから奇妙な例外がスローされ、何年も悩まされてきました。

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そして、この問題のトラブルシューティングを開始する方法さえ知りません。1 日に 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 サーバーがアプリケーションをシャットダウンし、すべてのバックグラウンド スレッドとブロック メソッドをキャンセルしただけでしょうか?

4

5 に答える 5

52

serverSocketが別のスレッドから閉じられている可能性はありますか?これにより、この例外が発生します。

于 2008-08-29T11:14:51.233 に答える
7

これは、WSAcancelblablabla を回避するための私のソリューション例です。スレッドをグローバルとして定義すると、次のように呼び出しメソッドを使用できます。

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 を閉じてからリスナーを停止します。

于 2011-12-06T08:37:18.237 に答える
5

これは、 で発生する可能性があり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);
}

今起こったことは、_disposedtrueに設定される前に例外が頻繁に発生することでした。したがって、私にとっての解決策は、すべてをスレッドセーフにすることでした。

于 2008-11-04T10:00:53.303 に答える
3

こっちも一緒!しかし、「サーバー側」のReceiveBufferがクライアントからあふれていることがわかりました! (私の場合、次の TagCode が到着するまで送信を停止する代わりに、TagCode をスパムし続けた RFID スキャナーの束)

ReceiveBuffersを上げてスキャナーを再構成するのに役立ちました...

于 2011-08-26T11:37:45.180 に答える