Время начала / получения / ожидания - PullRequest
15 голосов
/ 12 августа 2010

Я использую NetworkStream & TcpClient для асинхронного получения данных с использованием BeginRead.Мне нужно применить тайм-аут к этой операции, чтобы через определенное время чтение было прервано.

Насколько я могу судить, это не поддерживается в NetworkStream или TcpClient - есть свойство ReceiveTimeout, но, похоже, это применимо только к синхронному эквиваленту - 'Read'.

Даже базовый класс Socket не поддерживает тайм-ауты в своем методе BeginReceive.

Я искал по этой проблеме, и единственное предлагаемое решение, которое я видел, это настроить другой фоновый поток для отмены операции, если она не завершится в течение периода ожидания.Это похоже на ужасный взлом.Конечно, есть лучший способ?

Ответы [ 2 ]

2 голосов
/ 21 апреля 2011

Это единственный способ сделать это, потому что когда вы используете асинхронную операцию, поток, инициировавший операцию, отключается, делая что-то еще.Тайм-аут доступен для синхронной версии, потому что поток выполнения блокируется до завершения операции чтения.

Если вам придется использовать фоновый поток для отмены операции, не будет особого смыслапродолжая использовать асинхронные методы Begin / End.Если вы собираетесь раскрутить фоновый поток, просто выполните синхронную операцию чтения из фонового потока, а затем вы можете использовать ReceiveTimeout.

1 голос
/ 12 июля 2012

Ожидание 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();
}
...