Exception WSACancelBlockingCall

Ok, j’ai une exception étrange tirée de mon code qui me dérange depuis longtemps.

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 n’est pas très utile à ce sujet: http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx et je ne sais même pas comment commencer à résoudre ce problème. Il n’est lancé que 4 ou 5 fois par jour et jamais dans notre environnement de test. Seulement dans les sites de production et sur TOUS les sites de production.

J’ai trouvé beaucoup de messages demandant à propos de cette exception, mais pas de réponses définitives sur son origine et sur la manière de la gérer ou de la prévenir.

Le code s’exécute dans un thread d’arrière-plan distinct, la méthode démarre:

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

puis je lance une boucle en mettant toutes les nouvelles connexions en tant que travaux dans un pool de threads séparé. Cela devient plus compliqué à cause de l’architecture de l’application, mais essentiellement:

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

De là, le pool a ses propres threads qui prennent en charge chaque travail dans son propre thread, séparément.

Ma compréhension est que AcceptTcpClient () est un appel bloquant, et que D’une manière ou d’une autre, winsock dit au thread d’arrêter de bloquer et de continuer l’exécution. Mais pourquoi? Et que dois-je faire? Juste attraper l’exception et l’ignorer?


Eh bien, je pense qu’un autre thread ferme le socket, mais ce n’est certainement pas de mon code. Ce que je voudrais savoir, c’est: cette socket est-elle fermée par le client qui se connecte (de l’autre côté du socket) ou est-elle fermée par mon serveur? En l’état actuel des choses, chaque fois que cette exception se produit, il ferme mon port d’écoute et ferme mon service. Si cela se fait depuis un emplacement distant, alors c’est un problème majeur.

Sinon, cela pourrait-il être simplement le serveur IIS qui ferme mon application et annule ainsi tous mes threads d’arrière-plan et toutes mes méthodes de blocage?

Est-il possible que le serverSocket soit fermé d’un autre thread? Cela provoquera cette exception.

Voici mon exemple de solution pour éviter WSAcancelblablabla: Définissez votre thread comme global puis utilisez la méthode invoke comme ceci:

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

Après l’avoir appelé, fermez d’abord le thread, puis l’indicateur de boucle à jamais pour qu’il bloque davantage l’attente (si vous en avez), puis fermez tcpclient puis arrêtez l’écouteur.

Cela pourrait arriver sur un serverSocket.Stop() . Ce que j’ai appelé chaque fois que Dispose été appelé.

Voici à quoi ressemblait ma gestion des exceptions pour le thread d’écoute:

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

Maintenant, ce qui s’est passé, c’est que de temps en temps l’exception se produit avant que _disposed soit défini sur true. Donc, la solution pour moi était de rendre tout le thread sûr.

Pareil ici! Mais j’ai compris que le ReceiveBuffer sur «côté serveur» était inondé par les clients! (Dans mon cas, un groupe de scanners RFID, qui continuaient à spammer le TagCode, au lieu d’arrêter d’envoyer jusqu’à l’arrivée du prochain TagCode)

Cela a aidé à augmenter les ReceiveBuffers et à reconfigurer les scanners …

Plus récemment, j’ai vu cette exception lors de l’utilisation de HttpWebRequest pour PUT un fichier volumineux et le délai d’attente a été dépassé.

En utilisant le code suivant tant que votre temps de téléchargement> 3 secondes, cela provoquera cette erreur dans la mesure où je pourrai le voir.

 ssortingng 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(); }