Frage

Ok, ich habe eine seltsame Ausnahme in meinem Code, die mich schon seit Ewigkeiten stört.

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 ist hier nicht besonders hilfreich: http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx und ich weiß nicht einmal, wie ich mit der Fehlerbehebung beginnen soll.Es wird nur 4 oder 5 Mal am Tag ausgelöst und in unserer Testumgebung nie.Nur an Produktionsstandorten und an ALLEN Produktionsstandorten.

Ich habe viele Beiträge gefunden, in denen nach dieser Ausnahme gefragt wurde, aber keine wirklich endgültigen Antworten darauf, was sie verursacht und wie man damit umgeht oder sie verhindert.

Der Code läuft in einem separaten Hintergrundthread, die Methode startet:

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

Dann führe ich eine Schleife aus und lege alle neuen Verbindungen als Jobs in einen separaten Thread-Pool.Aufgrund der App-Architektur wird es komplizierter, aber grundsätzlich gilt:

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

Von dort aus ist die pool verfügt über eigene Threads, die jeden Job in einem eigenen Thread separat erledigen.

Meines Wissens nach ist AcceptTcpClient() ein blockierender Aufruf und Winsock weist den Thread irgendwie an, die Blockierung zu beenden und mit der Ausführung fortzufahren.aber warum?Und was soll ich tun?Einfach die Ausnahme abfangen und ignorieren?


Nun ja, ich glaube, dass ein anderer Thread den Socket schließt, aber das stammt ganz sicher nicht aus meinem Code.Was ich gerne wissen würde, ist:Wird dieser Socket vom verbindenden Client (auf der anderen Seite des Sockets) geschlossen oder wird er von meinem Server geschlossen?Denn so wie es in diesem Moment ist, wird bei jedem Auftreten dieser Ausnahme mein Überwachungsport geschlossen, wodurch mein Dienst effektiv geschlossen wird.Wenn dies von einem entfernten Standort aus geschieht, ist das ein großes Problem.

Könnte dies alternativ einfach der IIS-Server sein, der meine Anwendung herunterfährt und damit alle meine Hintergrundthreads und Blockierungsmethoden abbricht?

War es hilfreich?

Lösung

Ist es möglich, dass der serverSocket von einem anderen Thread geschlossen wird?Das wird diese Ausnahme verursachen.

Andere Tipps

Dies ist meine Beispiellösung, um WSAcancelblablabla zu vermeiden:Definieren Sie Ihren Thread als global, dann können Sie die Aufrufmethode wie folgt verwenden:

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

Nachdem Sie es aufgerufen haben, schließen Sie zuerst den Thread und dann das Flag für die Endlosschleife, damit es weiteres Warten blockiert (falls vorhanden). Schließen Sie dann tcpclient und stoppen Sie dann den Listener.

Dies könnte auf einem passieren serverSocket.Stop().Den ich jedes Mal angerufen habe Dispose hieß.

So sah meine Ausnahmebehandlung für den Listen-Thread aus:

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

Was nun passierte, war, dass die Ausnahme immer wieder einmal auftrat _disposed wurde auf true gesetzt.Die Lösung für mich bestand also darin, alles threadsicher zu machen.

Ebenfalls!Aber ich habe herausgefunden, dass der Empfangspuffer auf der Serverseite von den Clients überflutet wurde!(In meinem Fall ein Haufen RFID-Scanner, die den TagCode immer wieder spammten, anstatt mit dem Senden aufzuhören, bis der nächste TagCode eintrifft)

Es hat geholfen, die Empfangspuffer zu erhöhen und die Scanner neu zu konfigurieren ...

Kürzlich habe ich diese Ausnahme gesehen, als ich HttpWebRequest zum PUT einer großen Datei verwendet habe und der Timeout-Zeitraum überschritten wurde.

Wenn Sie den folgenden Code verwenden, solange Ihre Upload-Zeit > 3 Sekunden beträgt, wird dieser Fehler meines Erachtens verursacht.

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();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top