Asynchronous 开始接收/开始接收超时

Asynchronous 开始接收/开始接收超时,asynchronous,tcpclient,networkstream,beginreceive,beginread,Asynchronous,Tcpclient,Networkstream,Beginreceive,Beginread,我使用NetworkStream&TcpClient使用BeginRead异步接收数据。我需要对此操作应用一个超时,以便在指定的时间量后读取将中止 据我所知,NetworkStream或TcpClient不支持此功能-有一个ReceiveTimeout属性,但它似乎只适用于同步等效项“Read” 甚至底层套接字类在其BeginReceive方法中似乎也不支持超时 我已经搜索了这个问题,我看到的唯一建议解决方案是设置另一个后台线程,如果操作没有在超时时间内完成,就取消操作。这似乎是一个可怕的黑客。

我使用NetworkStream&TcpClient使用BeginRead异步接收数据。我需要对此操作应用一个超时,以便在指定的时间量后读取将中止

据我所知,NetworkStream或TcpClient不支持此功能-有一个ReceiveTimeout属性,但它似乎只适用于同步等效项“Read”

甚至底层套接字类在其BeginReceive方法中似乎也不支持超时


我已经搜索了这个问题,我看到的唯一建议解决方案是设置另一个后台线程,如果操作没有在超时时间内完成,就取消操作。这似乎是一个可怕的黑客。当然还有更好的方法吗?

这是唯一的方法,因为当您使用异步操作时,启动该操作的线程正在停止执行其他操作。同步版本的超时可用,因为在读取操作完成之前,执行线程被阻塞

但是,如果必须使用后台线程来取消操作,那么继续使用异步开始/结束方法就没有多大意义了。如果要剥离后台线程,只需从后台线程执行同步读取操作,然后就可以使用ReceiveTimeout。

等待并使用某个超时值在任务完成时发出信号。若它在发出信号之前超时,那个么您就知道异步操作永远不会完成

private ManualResetEvent receiveDone = new ManualResetEvent(false);

receiveDone.Reset();
socket.BeginReceive(...);
if(!receiveDone.WaitOne(new TimeSpan(0, 0, 0, 30))) //wait for 30 sec.
    throw new SocketException((int)SocketError.TimedOut);
在BeginReceive回调中,使用

private void ReceiveCallBack(IAsyncResult ar)
{
    /** Use ar to check if receive is correct and complete */
    receiveDone.Set();
}

Joel为我们指出了不使用后台线程来取消连接的正确方向,但如果不是很明显,很多人会使用1个线程(可能来自worker民意测验)定期清理死掉的连接。这是释放套接字句柄/etc所必需的,尤其是当您遇到拒绝服务攻击时(无论是有意还是无意)。另一个选项是,它不占用线程。@hangar有4种实现
Timer
System.Threading.Timer
占用线程,它只在线程池上运行,因此您不必手动管理计时器功能所需的资源。投否决票,因为这正是我(天真地)所做的,它不起作用。对
BeginReceive
的每次调用如果与对
EndReceive
的调用不匹配,就会泄漏内核资源。用Perfmon之类的图形表示流程活动,并观察非页面化池慢慢泄漏。如果这种情况持续足够长的时间(在我的例子中是几个小时),您最终会得到一个异常,错误代码为
WSAENOBUFS
;“无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满。”我尚未验证该操作,但在引发异常之前,我们能否通过调用
socket.EndReceive(…)
来解决您的问题?调用“EndReceive”所需的IAsyncResult由
BeginReceive
返回。对你的评论投赞成票。谢谢你的更新。所以。。。毕竟,这不是异步操作。我的意思是,使用BeginReceive有什么意义?如果你阻止线程直到超时?只需使用套接字超时的同步操作即可。。