16

我正在使用 NetworkStream 和 TcpClient 使用 BeginRead 异步接收数据。我需要对此操作应用超时,这样在指定的时间后读取将被中止。

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

甚至底层的 Socket 类似乎也不支持其 BeginReceive 方法中的超时。

我已经搜索过这个问题,我看到的唯一建议的解决方案是设置另一个后台线程来取消操作,如果它没有在超时期限内完成。这似乎是一个可怕的黑客攻击。肯定有更好的方法吗?

4

2 回答 2

2

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

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

于 2011-04-21T04:55:34.597 回答
1

等待具有一些超时值的ManualResetEvent以在您的任务完成时发出信号。如果它在发出信号之前超时,那么您就知道异步操作从未完成。

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();
}
于 2012-07-12T06:54:06.183 回答