Can I call stream.Close from another thread?

1k Views Asked by At

Can I safely close a System.IO.Stream (or any of the wrappers or Readers) from a second thread?

I've a new System.IO.StreamReader(inputStream, Encoding.ASCII); reading from network, and am considering shutting it down from another thread by closing it.

If this is not a good idea then what's another way of forcing the thread blocking in a read call from returning?

4

There are 4 best solutions below

0
JaredPar On BEST ANSWER

No it is not safe to blindly call the Close method from a separate thread. The Stream class is not listed as thread safe and calling Close from another thread while the original thread is using it will result in undefined behavior.

0
Mark Heath On

Yes, if inputStream is reading from a socket, then you can dispose on another thread which will close the socket connection. You should be aware that the blocking Read call will throw an exception.

2
Nader Shirazie On

A common approach to clean up tidily in this situation is:

  1. Set a value that indicates completion (eg IsDone = true)
  2. Write some data to the socket so that the blocking read gets some data
  3. On the thread that is reading from the socket, check if IsDone is true before processing the read data. If IsDone is true, ignore the data, and close the stream.

This should avoid any of the issues Jared is referencing.

4
Jeff Tucker On

Yes, it's fine to close a stream on another thread but be aware of the consequences of doing so. If you do and another thread is using that stream, you'll get an exception. The correct thing to do is to have either an event or a wait handle that the thread doing the reading can check to see if it should shut down. The pseudocode would look something like this: Thread 1. pend a read operation and see if there's data to be read.
if ther's data, read some data. if not, continue check the wait handle. If it's set, close it and terminate otherwise read some more loop

Thread 2. If I should trigger the network to disconnect, signal the wait handle else do whatever.

Be aware that if you're on a blocking operation, you'll get an exception. I recommend NEVER using a blocking socket, there's no reason to. We actually do (almost) all of our operations async under the hood of System.Net and the sync code paths just trigger the async code path and then block until they complete.