首页 文章

WSACancelBlockingCall异常

提问于
浏览
41

好吧,我的代码抛出一个奇怪的例外,这个例子一直困扰着我多年 .

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 分别拥有自己的线程's own threads that take care of each job in it' .

我的理解是AcceptTcpClient()是一个阻塞调用,并且不知何故winsock告诉线程停止阻塞并继续执行..但为什么呢?那我该怎么办? grab 异常并忽略它?


好吧,我确实认为其他一些线程正在关闭套接字,但它肯定不是来自我的代码 . 我想知道的是:这个套接字是由连接客户端(在套接字的另一端)关闭还是由我的服务器关闭 . 因为就在这时,每当发生此异常时,它会关闭我的侦听端口,从而有效地关闭我的服务 . 如果这是从远程位置完成的,那么这是一个主要问题 .

或者,这可能只是IIS服务器关闭我的应用程序,从而取消所有我的后台线程和阻止方法?

5 回答

  • 5

    是否有可能从另一个线程关闭serverSocket?这将导致此异常 .

  • 38

    这是我避免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然后停止监听器 .

  • 4

    这可能发生在 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之前,每隔一段时间就会发生异常 . 因此,我的解决方案是使一切线程安全 .

  • 0

    同样在这里!但我想通了,“服务器端”的ReceiveBuffer被客户端淹没了! (在我的情况下,一堆RFID扫描仪,他们不断发送垃圾信息,而不是停止发送,直到下一个TagCode到达)

    它有助于提升ReceiveBuffers并重新配置扫描仪......

  • 3

    最近,当使用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();
    }
    

相关问题