我正在实现一个简单的本地网络发现协议,所以我先调用UdpClient.Send,然后调用UdpClient.BeginReceive。如果有多个响应挂起,我会在回调结束时调用UdpClient.BeginReceive。如下所示:
UdpClient client = new UdpClient(AddressFamily.InterNetwork);
client.EnableBroadcast = true;
client.Send(request, request.Length, broadcastEndPoint);
client.BeginReceive(Callback, client);然后在Callback中使用...and
void Callback(IAsyncResult ar)
{
UdpClient client = (UdpClient)ar.AsyncState;
IPEndPoint remoteEndPoint = null;
byte[] response = client.EndReceive(ar, ref remoteEndPoint);
// Do something with response
client.BeginReceive(Callback, client);
}我的问题是,我的主循环在接收挂起时调用client.Close。接收完成,然后我对BeginReceive的下一次调用抛出一个异常:System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
为什么UdpClient没有CancelReceive方法?我能做些什么呢?
发布于 2013-10-16 00:00:20
使用"isClosing“标志来通知回调函数该UdpClient不再可用不是一个合适的解决方案。当回调在不同的线程中执行时,连接总是有可能在"isClosing“标志检查之后、"BeginReceive”(或"EndReceive")调用之前关闭。
尽管这不是一个干净的设计,但微软似乎建议只捕获相应的异常来检测套接字不再可用。没有记录"BeginReceive",但这就是documented for the similar function "BeginConnect":
若要取消对BeginConnect()方法的挂起调用,请关闭套接字。当异步操作正在进行时调用Close()方法时,将调用提供给BeginConnect()方法的回调。随后对EndConnect(IAsyncResult)方法的调用将抛出一个ObjectDisposedException,以指示操作已被取消。
因此,示例代码将如下所示:
void Callback(IAsyncResult ar)
{
try
{
UdpClient client = (UdpClient)ar.AsyncState;
IPEndPoint remoteEndPoint = null;
byte[] response = client.EndReceive(ar, ref remoteEndPoint);
// Do something with response
client.BeginReceive(Callback, client);
}
catch (SocketException e)
{
// Oups, connection was closed
}
catch (ObjectDisposedException e)
{
// Oups, client was disposed
}
}发布于 2009-09-08 07:16:38
相反,要克服此异常,请在发出close命令之前创建bool并设置它,使用bool签入回调
像这样
bool isClosing=false;
void Callback(IAsyncResult ar)
{
if(isClosing) return;
}在发出close命令之前设置bool isClosing
https://stackoverflow.com/questions/840090
复制相似问题