C# WSACancelBlockingCall 异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:10:22  来源:igfitidea点击:

WSACancelBlockingCall exception

提问by Radu094

Ok, I have a strange exception thrown from my code that's been bothering me for ages.

好的,我的代码抛出了一个奇怪的异常,这个异常一直困扰着我多年。

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 isn't terribly helpful on this : http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspxand I don't even know how to begin troubleshooting this one. It's only thrown 4 or 5 times a day, and never in our test environment. Only in production sites, and on ALL production sites.

MSDN 在这方面并不是很有帮助:http: //msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx,我什至不知道如何开始解决这个问题。它每天只抛出 4 或 5 次,而且从未在我们的测试环境中。仅在生产站点和所有生产站点上。

I've found plenty of posts asking about this exception, but no actual definitive answers on what is causing it, and how to handle or prevent it.

我发现有很多帖子询问这个异常,但没有关于导致它的原因以及如何处理或防止它的实际明确答案。

The code runs in a separate background thread, the method starts :

代码在单独的后台线程中运行,方法启动:

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

then I run a loop putting all new connections as jobs in a separate thread pool. It gets more complicated because of the app architecture, but basically:

然后我运行一个循环,将所有新连接作为作业放在单独的线程池中。由于应用程序架构,它变得更加复杂,但基本上:

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

From there, the poolhas it's own threads that take care of each job in it's own thread, separately.

从那里开始,它pool有自己的线程,分别处理自己线程中的每个工作。

My understanding is that AcceptTcpClient() is a blocking call, and that somehow winsock is telling the thread to stop blocking and continue execution.. but why? And what am I supposed to do? Just catch the exception and ignore it?

我的理解是 AcceptTcpClient() 是一个阻塞调用,并且 winsock 以某种方式告诉线程停止阻塞并继续执行..但为什么呢?我该怎么办?只是捕获异常并忽略它?



Well, I do think some other thread is closing the socket, but it's certainly not from my code. What I would like to know is: is this socket closed by the connecting client (on the other side of the socket) or is it closed by my server. Because as it is at this moment, whenever this exception occurs, it shutsdown my listening port, effectively closing my service. If this is done from a remote location, then it's a major problem.

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

Alternatively, could this be simply the IIS server shutting down my application, and thus cancelling all my background threads and blocking methods?

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

采纳答案by TimK

Is it possible that the serverSocket is being closed from another thread? That will cause this exception.

serverSocket 是否有可能被另一个线程关闭?那会导致这个异常。

回答by TimK

This could happen on a serverSocket.Stop(). Which I called whenever Disposewas called.

这可能发生在serverSocket.Stop(). 每当Dispose被调用时我都会调用它。

Here is how my exception handling for the listen thread looked like:

这是我对侦听线程的异常处理的样子:

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

Now what happened was, every so often the exception would occur before _disposedwas set to true. So the solution for me was to make everything thread safe.

现在发生的事情是,之前发生的异常经常_disposed被设置为 true。所以我的解决方案是让一切线程安全。

回答by blogga

Same here! But i figured out, that the ReceiveBuffer on 'server-side' was flooded from the clients! (In my case a bunch of RFID-Scanners, who kept spamming the TagCode, instead of stop sending until next TagCode arrives)

同样在这里!但我发现,“服务器端”的 ReceiveBuffer 被客户端淹没了!(在我的情况下,一群 RFID 扫描器,他们一直在向 TagCode 发送垃圾邮件,而不是在下一个 TagCode 到达之前停止发送)

It helped to raise the ReceiveBuffers and reconfigure the scanners...

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

回答by Nikolaus Very Permana

This is my example solution to avoid WSAcancelblablabla: Define your thread as global then you can use invoke method like this:

这是我避免 WSAcancelblablabla 的示例解决方案:将您的线程定义为全局然后您可以使用这样的 invoke 方法:

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

After you invoke it, close the thread first then the forever loop flag so it block further waiting (if you have it), then close tcpclient then stop the listener.

调用它后,先关闭线程,然后关闭永久循环标志,以便阻止进一步等待(如果有),然后关闭 tcpclient,然后停止侦听器。

回答by SimonNZ

More recently I saw this exception when using HttpWebRequest to PUT a large file and the Timeout period was passed.

最近,我在使用 HttpWebRequest 放置大文件并且超时期限已过时看到了此异常。

Using the following code as long as your upload time > 3 seconds it will cause this error as far as I could see.

只要您的上传时间> 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();
}