As noted, FileStream is not thread-safe.  You're mistaken as to what
OVERLAPPED really does for you.

The implementation using OVERLAPPED is not thread safe.  Overlapped IO is
used merely to get asynchronous operations (via BeginWrite() or BeginRead
(), to get synchronous operations delete the "Begin"), meaning your one
thread can continue to do something else while the OS is performing the
operation.  This has nothing to do with your application being multi-
threaded or not.

By using only one OVERLAPPED structure, only one read/write operation can
be pending at a time (hence the thread-unsafeness).  For example, how
could two operations (presumably on two threads) be synchronized on the
one event handle in the OVERLAPPED structure?

Even if you wrote native code with CreateFile, ReadFile, and/or WriteFile
with one OVERLAPPED structure you'd have the same problem; you'd have to
synchronize multi-threaded access to the OVERLAPPED structure (i.e only
one thread can be waiting for a pending operation at a time).  You're more
than free to have more than one OVERLAPPED structure, one per thread; but,
in .NET you have to use one FileStream per thread to duplicate this
functionality.

http://www.peterRitchie.com/


On Thu, 15 Dec 2005 10:01:39 -0500, John Davis <[EMAIL PROTECTED]> wrote:

>Ian I'm afraid you're really mistaken on this one.
>
>What I'm looking for is the equivalent of a ReadFile or WriteFile call
>where the offset is passed in the OVERLAPPED struct.  The call can occur
>through overlapped IO, or an IO completion port.  The call is also atomic.
>
>There needs to be a random access async read/write of some sort which uses
>the OVERLAPPED struct in the Win32 API in that it has a file offset field
>for the read or write.  If one observes the current implementation in
>DotNetReflector, the OVERLAPPED struct is getting populated via the
>FileStream Seek call.  The OVERLAPPED struct is then used on the next
>async write.  Why implement it this way if FileStreams can only be used by
>a single thread?  This is a bit of a cluster if you ask me.
>
>On Thu, 26 May 2005 23:22:45 +0100, Ian Griffiths <[EMAIL PROTECTED]>
>wrote:
>
>>Even if there were an atomic method how would that help?  It wouldn't
>>eliminate the race condition, because it would still be illegal to call
>>the method simultaneously on multiple threads. (FileStream's
>>documentation says it's illegal to do that.)  So you'd still need to use
>>locking or some other synchronization method to make sure your threads
>>take it in turns even if there were an atomic method.
>>
>>I agree it would be cleaner to have a random access method if random
>>access is what you're doing - a stream isn't really the right
>>abstraction in that case.  (Sadly it's the only one we're offered
>>AFAIK.)
>>
>>But is this a defect?  It's a bug to use a stream from multiple threads
>>without synchronization.  It would still be a bug even with the atomic
>>method you propose.
>>
>>
>>--
>>Ian Griffiths
>>http://www.interact-sw.co.uk/iangblog/
>>
>>> -----Original Message-----
>>> From: John Davis
>>>
>>> >Are you saying that locking, Seeking, BeginWriteing, and unlocking is
>>> not good enough?
>>>
>>> Well, I guess it is good enough, just doesn't seem very elegant.
>>Would be
>>> nice if there was an offset in there so one "atomic" call could be
>>made.
>>> Same as with Win32 overlapped io.
>>>
>>> >Does the BeginWrite not in effect take a snapshot of
>>> the seek location when the operation starts?
>>>
>>> I don't know for certain if it does, I certainly hope so.  Time to go
>>> digging with reflector I guess.
>>>
>>> Ian Griffiths <[EMAIL PROTECTED]> wrote:
>>> The documentation says that members of this class are not thread safe,
>>> so multiple threads shouldn't be using this at any given instance. You
>>> need to do some kind of locking if you have multiple threads using it.
>>>
>>> Are you saying that locking, Seeking, BeginWriteing, and unlocking is
>>> not good enough? Does the BeginWrite not in effect take a snapshot of
>>> the seek location when the operation starts?
>>>
>>>
>>> > -----Original Message-----
>>> > From: John Davis
>>> >
>>> > The way I understand it, the current BeginWrite on the
>>> > FileStream object will write out it's buffer at the location of
>>> > the last Seek. The problem comes when there are multiple threads
>>> > using the same FileStream instance.
>>> >
>>> > Each one is looking to write to a different offset in the file. This
>>> > means each thread must call FileStream.Seek followed by
>>> > FileStream.BeginWrite Obviously, this creates a race condition.
>>> >
>>> > Why isn't there an async BeginWrite, on the FileStream, with an
>>> > argument which specifies the offset within the file to write to.
>>> > It's possible to call WriteFileEx within the Win32 API with an
>>> > OVERLAPPED struct which specifies the offset. Why isn't this
>>> > exposed through the framework?
>>
>>===================================
>>This list is hosted by DevelopMentorĀ®  http://www.develop.com
>>
>>View archives and manage your subscription(s) at
>http://discuss.develop.com
>
>There needs to be a random access async read/write of some sort which uses
>the OVERLAPPED struct in the Win32 API in that it has a file offset field
>for the read or write.  If one observes the current implementation in
>DotNetReflector, the OVERLAPPED struct is getting populated via the
>FileStream Seek call.  The OVERLAPPED struct is then used on the next
>async write.  Why implement it this way if FileStreams can only be used by
>a single thread?  This is a bit of a cluster if you ask me.

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to