Question

Ok, j'ai une étrange exception levée dans mon code qui me dérange depuis des lustres.

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 par où commencer le dépannage de celui-ci.Il n'est lancé que 4 ou 5 fois par jour, et jamais dans notre environnement de test.Uniquement sur les sites de production, et sur TOUS les sites de production.

J'ai trouvé de nombreux articles portant sur cette exception, mais aucune réponse définitive sur sa cause et sur la manière de la gérer ou de l'empêcher.

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

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

puis j'exécute une boucle plaçant toutes les nouvelles connexions sous forme de tâches dans un pool de threads séparé.Cela devient plus compliqué à cause de l'architecture de l'application, mais en gros :

   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 s'occupent de chaque tâche dans son propre thread, séparément.

Je crois comprendre que AcceptTcpClient() est un appel bloquant et que, d'une manière ou d'une autre, Winsock dit au thread d'arrêter le blocage et de continuer l'exécution.mais pourquoi?Et qu'est-ce que je suis censé faire ?Il suffit d'attraper l'exception et de l'ignorer ?


Eh bien, je pense qu'un autre thread ferme le socket, mais cela ne vient certainement pas de mon code.Ce que j'aimerais savoir c'est :ce socket est-il fermé par le client qui se connecte (de l'autre côté du socket) ou est-il fermé par mon serveur.Parce que dans l’état actuel des choses, chaque fois que cette exception se produit, elle ferme mon port d’écoute, fermant ainsi mon service.Si cela est fait à distance, c'est un problème majeur.

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

Était-ce utile?

La solution

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

Autres conseils

Voici mon exemple de solution pour éviter WSAcancelblablabla :Définissez votre fil de discussion comme global, puis vous pouvez utiliser la méthode d'invocation comme celle-ci :

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

Après l'avoir invoqué, fermez d'abord le thread, puis l'indicateur de boucle permanente afin qu'il bloque toute attente supplémentaire (si vous l'avez), puis fermez tcpclient puis arrêtez l'écouteur.

Cela pourrait arriver sur un serverSocket.Stop().Que j'appelais à chaque fois Dispose a été appelé.

Voici à quoi ressemblait ma gestion des exceptions pour le fil d'écoute :

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

Or, ce qui s'est passé, c'est que de temps en temps, l'exception se produisait avant _disposed était défini sur vrai.La solution pour moi était donc de rendre tout thread-safe.

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

Cela a permis d'augmenter les ReceiverBuffers et de 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'expiration a été dépassé.

En utilisant le code suivant tant que votre temps de téléchargement est > 3 secondes, cela provoquera cette erreur pour autant que je puisse le voir.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top