Реализация таймаута с помощью NetworkStream.BeginRead и NetworkStream.EndRead - PullRequest
4 голосов
/ 08 октября 2011

Я написал следующую функцию для реализации функции тайм-аута с использованием функций асинхронного чтения NetworkStream (BeginRead и EndRead). Работает нормально, пока я не закомментирую строку Trace.WriteLine("bytesRead: " + bytesRead);. Почему?

private int SynchronousRead(byte[] buffer, int count)
{
    int bytesRead = 0;
    bool success = false;
    IAsyncResult result = null;

    result = _stream.BeginRead(
        buffer, 0, count,
        delegate(IAsyncResult r)
        {
            bytesRead = _stream.EndRead(r);
        },
        null);

    success = result.AsyncWaitHandle.WaitOne(_ioTmeoutInMilliseconds, false);

    if (!success)
    {
        throw new TimeoutException("Could not read in the specfied timeout.");
    }

    //If I remove this line, bytesRead is always 0
    Trace.WriteLine("bytesRead: " + bytesRead);

    return bytesRead;
}

На всякий случай, если вам интересно, я должен это сделать, потому что мне в конечном итоге потребуется нацелиться на .Net Compact Framework 3.5, и он не поддерживает свойства NetworkStream.ReadTimeout и NetworkStream.WriteTimeout.

Ответы [ 2 ]

5 голосов
/ 08 октября 2011

Интересная ошибка в потоке.Переменная bytesRead присваивается после о сигнале ожидания дескриптора.Две вещи могут пойти не так: метод возвращается до выполнения присваивания.Или поток читает устаревшие значения, так как они не являются барьером памяти после вызова WaitOne ().Оператор Trace решает проблему, потому что он задерживает основной поток достаточно долго, чтобы позволить переменной быть записанной.Кроме того, он имеет внутреннюю блокировку, которая обеспечивает целостность кэша.

Вам потребуется дополнительное AutoResetEvent, которое сигнализирует о записи переменной bytesRead.

0 голосов
/ 08 октября 2011

Помимо проблемы с барьером памяти в вашем коде (как указал Ганс), на вашем месте я бы использовал Reactive Extension вместо этого, чтобы сделать этот сегмент кода всего за три строки кода.Если у вас есть время, я настоятельно рекомендую вам вместо этого использовать Rx.

Приветствия

...