我已经使用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 Framework3.5为目标,而它不支持NetworkStream.ReadTimeout和NetworkStream.WriteTimeout属性。
发布于 2011-10-08 21:06:23
一个有趣的线程bug。bytesRead变量在等待句柄发出信号后赋值。有两件事可能出错:方法在赋值之前返回。或者线程读取一个陈旧的值,因为它们在WaitOne()调用之后没有内存屏障。Trace语句修复了这个问题,因为它会延迟主线程足够长的时间来允许写入变量。而且它有一个内部锁来确保缓存的一致性。
您将需要一个额外的AutoResetEvent来表明bytesRead变量已被写入。
发布于 2011-10-08 23:43:35
除了你代码中的内存障碍问题(正如Hans还指出的那样),如果我是你,我会使用反应式扩展,这将使这段代码只有三行代码。如果您有时间,我强烈建议您使用Rx。
干杯
https://stackoverflow.com/questions/7696856
复制相似问题