好的,我的代码中有一个奇怪的例外,这个例子一直困扰着我。
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
拥有自己的线程,分别处理它自己的线程中的每个作业。
我的理解是AcceptTcpClient()是一个阻塞调用,并且不知何故winsock告诉线程停止阻塞并继续执行..但为什么呢?那我该怎么办?抓住异常并忽略它?
好吧,我确实认为其他一些线程正在关闭套接字,但它肯定不是来自我的代码。 我想知道的是:这个套接字是由连接客户端(在套接字的另一端)关闭还是由我的服务器关闭。因为就在此时,每当发生此异常时,它都会关闭我的侦听端口,从而有效地关闭我的服务。如果这是从远程位置完成的,那么这是一个主要问题。
或者,这可能只是IIS服务器关闭我的应用程序,从而取消所有后台线程和阻塞方法?
答案 0 :(得分:41)
是否有可能从另一个线程关闭serverSocket?这将导致此异常。
答案 1 :(得分:6)
这是我避免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,然后停止监听器。
答案 2 :(得分: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之前,每隔一段时间就会发生异常。因此,我的解决方案是使所有线程安全。
答案 3 :(得分:3)
同样在这里! 但我想通了,“服务器端”的ReceiveBuffer被客户端淹没了! (在我的情况下,一堆RFID扫描仪,他们不断发送垃圾信息,而不是停止发送,直到下一个TagCode到达)
它有助于提升ReceiveBuffers并重新配置扫描仪......
答案 4 :(得分:0)
最近,当我使用HttpWebRequest放置大文件并经过超时期限时,我看到了此异常。
只要您的上传时间大于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();
}