WSACancelBlockingCall 异常

发布于 2024-07-05 10:09:11 字数 1475 浏览 9 评论 0原文

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

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

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

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


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

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

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).aspx and 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.

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 pool has it's own threads that take care of each job in it's own thread, separately.

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?


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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

醉梦枕江山 2024-07-12 10:09:12

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

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

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

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();
}
刘备忘录 2024-07-12 10:09:12

我们在 SSH.NET 中看到了这个 WSACancelBlockingCall 异常。 该异常被抛出,然后被 SSH.NET 在内部捕获。

Visual Studio中,调试 -> 窗口 -> 可能会设置异常设置,以便您看到错误,但它正在其自己的代码中正确处理。 当我将设置重置为默认值时,我们不再看到内部错误。

We saw this WSACancelBlockingCall exception with SSH.NET. This exception was thrown, then caught internally by SSH.NET.

In Visual Studio, Debug -> Windows -> Exception Settings might be set so that you see the error, but it is being handled correctly within its own code. When I reset the settings to the Default, we no longer saw the internal error.

顾挽 2024-07-12 10:09:11

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

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

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)

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

罗罗贝儿 2024-07-12 10:09:11

这可能发生在 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);
}

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

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

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 _disposed was set to true. So the solution for me was to make everything thread safe.

呆萌少年 2024-07-12 10:09:11

这是我避免 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();
    }

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

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

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.

花开雨落又逢春i 2024-07-12 10:09:11

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文