Asynchronous methods(!) clarification in .net?

2019-07-18 09:45发布

问题:

I've been reading a lot lately about this topic and , still I need to clarify something

The whole idea with asynchronous methods is Thread economy :

Allow many tasks to run on a few threads. this is done by using the hardware driver to do the job while releasing the thread back to the thread-pool so it can server other jobs.

please notice .

I'm not talking about asynchronous delegates which ties another thread (execute a task in parallel with the caller).

However I've seen 2 main types of asynchronous methods examples :

  • Code samples (from books) who only uses existing I/O asynchronous operations as beginXXX / endXX e.g. Stream.BeginRead.
    And I couldn't find any asynchronous methods samples which don't use existing .net I/O operations e.g. Stream.BeginRead )

  • Code samples like this (and this). which doesnt actually invoking an asynchronous operation (although the author thinks he is - but he actually causes a thread to block !)

Question :

Does asynchronous methods are used only with .net I/O existing methods like BeginXXX , EndXXX ?

I mean , If I want to create my own asynchronous methods like BeginMyDelay(int ms,...){..} , EndMyDelay(...). I couldn't done it without tie a blocked thread to it....correct?

Thank you very much.

p.s. please notice this question is tagged as .net 4 and not .net4.5

回答1:

You're talking about APM. APM widely uses OS concept, known as IO Completion ports. That's why different IO operations are the best candidates to use APM.

You could write your own APM methods. But, in fact, these methods will be either over existing APM methods, or they will be IO-bound, and will use some native OS mechanism (like FilesStream, which uses overlapped file IO).

For compute-bound asynchronous operations APM only will increase complexity, IMO.

A bit more clarification.

Work with hardware is asynchronous by its nature. Hardware needs a time to perform request - newtork card must send or receive data, HDD must read/write etc. If IO is synchronous, thread, which was generated IO request, is waiting for response. And here APM helps - you shouldn't wait, just execute something else, and when IO will be complete, I'll call you, says APM.

The main point - operation is performing outside of CPU.

When you're writing any compute-bound operation, which will use CPU for it execution without any IO, there's nothing to wait here. So, APM coludn't help - if you need CPU, you need thread - you need thread pool.



回答2:

I think, but I'm not sure, that you can create your own asynchronous methods. For example creating a new thread and wait for it to finish some work (db query, ...).

In term of overall system performance probably it is not useful, as you say you just create another thread. But for example if you work on IIS, the original request thread can be used for other requests while you are waiting for the 'background' operation.

I think that IIS has a fixed number of threads (thread pool), so in this case can be useful.



回答3:

I mean , If I want to create my own asynchronous methods like BeginMyDelay(int ms,...){..} , EndMyDelay(...). I couldn't done it without tie a blocked thread to it....correct?

While I've not dug into the implementation of async, I can't see any reason why one couldn't do this.

The simplest way would be to use existing libraries that help [e.g. timers] or some sort of event system IIRC.

However even if you don't want to use any library helpers then you're stuck with a problem... the 'blocked thread'.

Sure the code does look something like this:

while (true){
      foreach (var item in WaitingTasks)
              if (item.Ready())
                 /*fire item, and remove it from tasks*/;

      /*Some blocking action*/
}

Thing is - 'Some blocking action' doesn't have to be 'blocking'. You could yield/sleep the thread, or use it to process some data. For example, the Unity Game Engine does a similar thing with Coroutines - where the same thread that processes all the code also checks to see if various coroutines [that have been delayed due to time] need to be updated. Replace /*Some blocking action*/ with ProcessGameLoop().

Hoe that helps, feel free to ask questions/post corrections etc.