Подтвердить что ты не робот

Исключение WSACancelBlockingCall

Хорошо, у меня есть странное исключение из моего кода, который беспокоил меня целую вечность.

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, завершающий мое приложение и, таким образом, отменя все мои фоновые потоки и методы блокировки?

4b9b3361

Ответ 1

Возможно ли, что serverSocket закрывается из другого потока? Это вызовет это исключение.

Ответ 2

Это мое примерное решение, чтобы избежать 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();
    }

После того, как вы его вызовете, сначала закройте поток, а затем флаг forever loop, чтобы заблокировать дальнейшее ожидание (если оно у вас есть), затем закройте tcpclient и остановите прослушиватель.

Ответ 3

Это может произойти на 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. Поэтому решение для меня состояло в том, чтобы сделать все потоки безопасными.

Ответ 4

То же самое! Но я понял, что ReceiveBuffer на стороне сервера был затоплен от клиентов! (В моем случае куча RFID-сканеров, которые продолжали спамить TagCode, вместо того, чтобы прекратить отправку, пока не появится следующий TagCode)

Это помогло поднять ReceiveBuffers и переконфигурировать сканеры...