Deploying a timeout using NetworkStream.BeginRead and NetworkStream.EndRead

I wrote the following function to implement the timeout function using the asynchronous NetworkStream reading functions ( BeginRead and EndRead ). It works fine until I comment out the line Trace.WriteLine("bytesRead: " + bytesRead); . Why?

 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; } 

Just in case you are interested, I have to do this because I will eventually need to configure the .NET Compact Framework 3.5 and do not support the NetworkStream.ReadTimeout and NetworkStream.WriteTimeout properties.

+4
source share
2 answers

Interesting streaming error. The bytesRead variable is assigned after the wait command is signaled. Two things can go wrong: the method returns before the task is completed. Or the thread reads an obsolete value, since they are not memory protection from calling WaitOne (). The Trace statement fixes the problem because it delays the main thread long enough to allow writing to the variable. And it has an internal lock that ensures cache integrity.

You will need an optional AutoResetEvent that signals that the bytesRead variable has been written.

+5
source

Besides the problem with the memory barrier in your code (as Hans pointed out), if I were you, I would use the Reactive Extension instead, so that this code segment consists of only three lines of code. If you have time, I highly recommend that you use Rx instead.

Greetings

0
source

All Articles