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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
49
0
86 370
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

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

Скажи, что это так. Как закрыть его из другой ветки? Должен ли сокет быть «энергозависимым»?

zkwentz 27.03.2011 00:21

Нет, пока другой поток имеет ссылку на объект сокета, он может закрыть его.

TimK 30.03.2011 18:31

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

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

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

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

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

InvokeRequired связывает ваше решение с winforms. Что делать, если код выполняется в службе Windows?

Micah Epps 14.11.2019 22:35

Совсем недавно я видел это исключение при использовании HttpWebRequest для PUT большого файла, и период тайм-аута был пройден.

Насколько я могу судить, использование следующего кода, если время загрузки> 3 секунд, вызовет эту ошибку.

string path = "Reasonably large file.dat";
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
System.Net.HttpWebRequest req = (HttpWebRequest)System.Net.HttpWebRequest.Create("Some URL");
req.Method = "PUT";
req.Timeout = 3000; //3 seconds, small timeout to demonstrate
long length = new System.IO.FileInfo(path).Length;
using (FileStream input = File.OpenRead(path))
{
    using (Stream output = req.GetRequestStream())
    {
        long remaining = length;
        int bytesRead = 0;
        while ((bytesRead = input.Read(buffer, 0, (int)Math.Min(remaining, (decimal)bufferSize))) > 0)
        {
            output.Write(buffer, 0, bytesRead);
            remaining -= bytesRead;
        }
        output.Close();
    }
input.Close();
}

Хм, я не понимаю, как это может мне помочь (у меня та же ошибка). Кстати, шаблон «using» уже вызывает для вас output.Close(); и input.Close();, так что не нужно делать это самостоятельно, иначе он будет вызываться дважды.

ForceMagic 28.04.2020 06:05

Другие вопросы по теме