好吧,我的代码抛出一个奇怪的例外,这个例子一直困扰着我多年.
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()
Run Code Online (Sandbox Code Playgroud)
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();
Run Code Online (Sandbox Code Playgroud)
然后我运行一个循环,将所有新连接作为作业放在一个单独的线程池中.由于应用程序架构,它变得更加复杂,但基本上:
while (( socket = serverSocket.AcceptTcpClient()) !=null) //Funny exception here
{
connectionHandler = new ConnectionHandler(socket, mappingStrategy);
pool.AddJob(connectionHandler);
}
}
Run Code Online (Sandbox Code Playgroud)
从那里开始,pool它拥有自己的线程,分别处理它自己的线程中的每个工作.
我的理解是AcceptTcpClient()是一个阻塞调用,并且不知何故winsock告诉线程停止阻塞并继续执行..但为什么呢?那我该怎么办?抓住异常并忽略它?
好吧,我确实认为其他一些线程正在关闭套接字,但它肯定不是来自我的代码.我想知道的是:这个套接字是由连接客户端(在套接字的另一端)关闭还是由我的服务器关闭.因为就在这时,每当发生此异常时,它会关闭我的侦听端口,从而有效地关闭我的服务.如果这是从远程位置完成的,那么这是一个主要问题.
或者,这可能只是IIS服务器关闭我的应用程序,从而取消所有我的后台线程和阻止方法?
小智 5
这可能在上发生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);
}
Run Code Online (Sandbox Code Playgroud)
现在发生的事情是,在_disposed设置为true 之前,经常会发生异常。因此,对我来说,解决方案是使所有线程安全。
小智 5
这是我避免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();
}
Run Code Online (Sandbox Code Playgroud)
在调用它之后,首先关闭线程然后关闭forever循环标志,以便阻止进一步等待(如果有的话),然后关闭tcpclient然后停止监听器.
| 归档时间: |
|
| 查看次数: |
73587 次 |
| 最近记录: |