C# 使用NetworkStream.BeginRead和NetworkStream.EndRead实现超时

C# 使用NetworkStream.BeginRead和NetworkStream.EndRead实现超时,c#,.net,asynchronous,networkstream,C#,.net,Asynchronous,Networkstream,我编写了以下函数,以使用NetworkStream的异步读取函数(BeginRead和EndRead)实现超时功能。在我注释掉行Trace.WriteLine(“bytesRead:+bytesRead”)之前,它工作正常。为什么? private int SynchronousRead(byte[] buffer, int count) { int bytesRead = 0; bool success = false; IAsyncResult result = nu

我编写了以下函数,以使用
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
属性。

一个有趣的线程错误。bytesRead变量在等待句柄发出信号后分配。有两件事可能出错:方法在赋值之前返回。或者线程读取一个过时的值,因为它们的值没有超过WaitOne()调用的内存障碍。Trace语句修复了这个问题,因为它将主线程延迟足够长的时间,以允许写入变量。它有一个内部锁,确保缓存的一致性


您将需要一个额外的AutoResetEvent来表示ByteRead变量已被写入。

除了代码中的内存障碍问题(正如Hans也指出的那样),如果我是您,我将使用反应式扩展来代替,这将使此代码段只包含三行代码。如果你有时间,我强烈建议你改用Rx


干杯

当你把那行评论掉时,会发生什么?任何异常/错误消息?@Yahia,如果我删除该行,
bytesRead
始终为0。如果我添加一个
线程.Sleep(1)
而不是
跟踪.WriteLine
,它也可以工作。这就好像没有给
\u stream.EndRead(r)
足够的时间。