Asynchronous I/O really saves resources?

M

Morgan Cheng

Asynchronous I/O is said to be using native completion port. However,
i checked rotor2.0 code, it seems not
in stream.cs. BeginRead is defined in below way. In my understanding,
If BeginInvoke is used, the task is queued; and when there is free
worker thread in ThreadPool, the task is performed in specified worker
thread. Then, Asynchronous I/O doesn't save thread in ThreadPool. Is
my understanding correct?


[HostProtection(ExternalThreading=true)]
public virtual IAsyncResult BeginRead(byte[] buffer, int
offset, int count, AsyncCallback callback, Object state)
{
if (!CanRead) __Error.ReadNotSupported();

// Increment the count to account for this async operation
BCLDebug.Assert(_asyncActiveCount >= 1, "ref counting
mismatch, possible race in the code");
Interlocked.Increment(ref _asyncActiveCount);

ReadDelegate d = new ReadDelegate(Read);

// To avoid a race with a stream's position pointer &
generating race
// conditions with internal buffer indexes in our own
streams that
// don't natively support async IO operations when there
are multiple
// async requests outstanding, we will block the
application's main
// thread if it does a second IO request until the first
one completes.
if (_asyncActiveEvent == null) {
lock(this) {
if (_asyncActiveEvent == null)
_asyncActiveEvent = new AutoResetEvent(true);
}
}
bool r = _asyncActiveEvent.WaitOne();
BCLDebug.Assert(r, "AutoResetEvent didn't get a signal
when we called WaitOne!");

BCLDebug.Assert(_readDelegate == null && _writeDelegate ==
null, "Expected no other readers or writers!");

// Set delegate before we call BeginInvoke, to avoid a
race
_readDelegate = d;
IAsyncResult asyncResult = d.BeginInvoke(buffer, offset,
count, callback, state);

return asyncResult;
}
 
J

Jon Skeet [C# MVP]

Asynchronous I/O is said to be using native completion port. However,
i checked rotor2.0 code, it seems not
in stream.cs. BeginRead is defined in below way. In my understanding,
If BeginInvoke is used, the task is queued; and when there is free
worker thread in ThreadPool, the task is performed in specified worker
thread. Then, Asynchronous I/O doesn't save thread in ThreadPool. Is
my understanding correct?

1) The code for Rotor isn't exactly the same as the code for .NET
2) You're looking at just Stream.BeginRead, which is virtual. Stream
itself can't use IO completion ports, as it doesn't know whether the
stream *actually* uses anything that IO completion ports are
interested in (think about StringReader, for example). Instead,
derived classes (such as FileStream) are responsible for providing
more performant implementations where appropriate.

Jon
 
M

Morgan Cheng

1) The code for Rotor isn't exactly the same as the code for .NET
Yes, but I suppose major design is same.
2) You're looking at just Stream.BeginRead, which is virtual. Stream
itself can't use IO completion ports, as it doesn't know whether the
stream *actually* uses anything that IO completion ports are
interested in (think about StringReader, for example). Instead,
derived classes (such as FileStream) are responsible for providing
more performant implementations where appropriate.

In some post, it is said FileStream is using completion port. In
FileStream.cs, it reads
return base.BeginRead(array, offset, numBytes, userCallback,
stateObject);
Simply call basclass(Stream)'s implementation.

Well, by calling BeginInvoke(), the queued task is surely called by
worker thread? or it is possible to be performed by I/O thread in
thread pool?
 
J

Jon Skeet [C# MVP]

Yes, but I suppose major design is same.

It was at one point - but I doubt that nearly as much work as gone
into optimising Rotor. Bear in mind that Rotor also works on non-MS
platforms, not all of which even *have* IO completion ports.
In some post, it is said FileStream is using completion port. In
FileStream.cs, it reads
return base.BeginRead(array, offset, numBytes, userCallback,
stateObject);
Simply call basclass(Stream)'s implementation.

For Rotor, right? Don't assume that's the same for .NET.
Well, by calling BeginInvoke(), the queued task is surely called by
worker thread? or it is possible to be performed by I/O thread in
thread pool?

That implementation will just use the thread pool, by the looks of it.
Again, don't assume the same is true for .NET itself.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top