Pergunta

Ok, eu tenho uma estranha exceção de meu código que vem me incomodando há algum tempo.

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ão é muito útil sobre isso : http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx e eu nem sei como começar a solucionar este.É jogado apenas 4 ou 5 vezes ao dia, e nunca em nosso ambiente de teste.Apenas em locais de produção, e em TODOS os locais de produção.

Eu encontrei muitos de posts perguntando sobre esta excepção, mas sem respostas definitivas sobre o que está causando isso, e como tratar ou prevenir.

O código é executado em um thread em segundo plano separado, o método começa :

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

em seguida, executar um loop de colocar todas as novas conexões à medida que os trabalhos em uma thread separada da piscina.Fica mais complicado por causa do app arquitetura, mas basicamente:

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

A partir daí, o pool tem a sua própria segmentos que cuidar de cada trabalho em uma thread separada.

Meu entendimento é que AcceptTcpClient() é uma chamada de bloqueio, e que, de alguma forma, winsock está dizendo a thread para interromper o bloqueio e continuar a execução..mas por quê?E o que é suposto eu fazer?Apenas capturar a exceção e ignorá-lo?


Bem, eu acho que algum outro thread está fechando o socket, mas certamente não é do meu código.O que eu gostaria de saber é:é esse soquete fechado pelo o cliente de conexão (do outro lado da ranhura) ou é fechado pelo meu servidor.Porque, como ele está neste momento, sempre que essa exceção ocorre, shutsdown minha porta de escuta, efetivamente fechar meu serviço.Se isso é feito a partir de um local remoto e, em seguida, é um grande problema.

Alternativamente, isso pode ser simplesmente o servidor de IIS encerrar a minha candidatura, e, assim, a anulação de todos os meus threads de fundo e o bloqueio de métodos?

Foi útil?

Solução

É possível que o serverSocket está sendo fechada a partir de outro thread?Que fará com que essa exceção.

Outras dicas

Este é o meu exemplo de solução para evitar WSAcancelblablabla:Definir sua linha global, em seguida, você pode usar o método invoke como este:

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

Depois de invocá-lo, fechar a thread primeiro, em seguida, o para sempre loop sinalizador para que ele bloco de esperar (se você tiver) e, em seguida, feche tcpclient, em seguida, parar o ouvinte.

Isso pode acontecer em um serverSocket.Stop().Que eu, sempre que Dispose foi chamado.

Aqui é como o meu tratamento de exceção para o ouvir thread parecido com:

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

Agora, o que aconteceu foi que, muitas vezes, a exceção se ocorrer antes _disposed foi definido como true.Portanto, a solução para mim foi fazer tudo thread-safe.

Mesmo aqui!Mas eu descobri, que o ReceiveBuffer em "servidor-lado', foi inundado de clientes!(No meu caso um monte de RFID-Scanners, que manteve-spam do TagCode, em vez de parar de enviar até a próxima TagCode chega)

Ele ajudou a elevar o ReceiveBuffers e reconfigurar os scanners...

Mais recentemente eu vi essa exceção quando usando HttpWebRequest para COLOCAR um ficheiro de grandes dimensões e o período de tempo limite foi ultrapassado.

Usando o código a seguir como seu tempo de upload > 3 segundos ele irá causar esse erro tão longe quanto eu podia ver.

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top