Asynchronous delegates vs Threads

2020-05-24 05:44发布

问题:

Replacing Threads (not ThreadPool Thread) with Asynchronous Delegates (Callbacks).

My Scenario: Spawn a Thread/del.beginInvoke() per Client.

According to me,

Reasons

  1. need for Notification via Callback / Call delegate again in Callback
  2. Avoid Thread Overhead, (delegates use Threadpool thread)
  3. Passing Arguments (Avoid Casting to object) and need return value from the method.

Correct me if above reasons are wrong.

  1. Is any other Reasons?
  2. What scenario i exactly need to do some stuff with Asynchronous Delegates that threads can't?
    3.Performance ?

Example

    public delegate void SendCallbackType();

    SendCallbackType senderdel= new SendCallbackType(SendData);

    public void StartSend() // This method Could be Called more than 700 times (Thread per Client)
    {
        senderdel.BeginInvoke(SendCallback,null);
                   // (or)
        Thread t = new Thread(new ThreadStart(ThreadSend));
        t.IsBackground = true;
        t.Start();
    }

  //Async Delegate
    void SendData()
    {
         string data = QueData.DeQueue();
         RaiseOnData(data); // Raise to event.
    }
    void SendCallback(IAsyncResult ar)
    {
        senderdel.BeginInvoke(SendCallback, null);
    }

 //Thread
  void ThreadSend()
  {
      while (true)
      {
         string data = QueData.DeQueue();
         RaiseOnData(data); // Raise to event.
      }
   }

From the above which option would be the best. Performance ?

回答1:

Your reasoning is correct. Async delegates use threads from the thread pool so they should be faster compared to manual thread creation. Be careful though with this in ASP.NET applications. Because you will be eating up worker threads that are normally used by ASP.NET to service requests and your application might very quickly run out of servicing capabilities.

Async delegates are fine for CPU intensive tasks. For I/O intensive tasks (such as reading streams, database calls and web service calls) you should use the BeginXXX, EndXXX methods offered directly by the corresponding classes (Stream, SqlConnection, WebClient, ...). This way you are not using any threads at all during the lengthy I/O operation. You are using I/O Completion Ports which is the best thing in terms of I/O bound tasks. It will be orders of magnitude more performant and resource cheap than any threads and pools of threads.

So to summarize:

  • For I/O intensive tasks use I/O Completion Ports. If the I/O intensive task is wrapped inside a poorly written library that doesn't offer this possibility use the TPL that was introduced in .NET 4.0.
  • For CPU intensive tasks use the TPL that was introduced in .NET 4.0.

And if you don't have .NET 4.0 use thread pool unless you are writing an ASP.NET application in which case you might resort to manual thread creation.

In general it is good practice to start using TPL and orient your methods as tasks so that you are ready for .NET 4.5 which introduces the async/await keywords.