Explaining Delegates in C# - Part 7 (Asynchronous Callback - Way 4)

本文详细解释了C#中异步回调的工作原理,通过实例展示了使用BeginInvoke和EndInvoke方法来实现异步操作的过程。文章还提供了一个简单的异步调用示例,包括如何在主线程中启动异步任务,以及如何在后台线程中执行回调方法。通过阅读本文,读者将能够更好地理解和应用C#中的异步编程技巧。

This is the final part of the series that started with...


One more Event
Asynchronous Callback - Way 1 - BeginInvoke > EndInvoke
Asynchronous Callback - Way 2 - BeginInvoke > AsyncWaitHandle.WaitOne(x) > EndInvoke > AsynWaitHandle.Close()
Asynchronous Callback - Way 3 - BeginInvoke > Poll for result's IsCompleted > EndInvoke

In this scenario, if we go with the husband-wife-kiddo analogy, I will need to introduce another guy! No no no... please don't misunderstand me... he is the just the driver Winking

So, now the husband drops his wife at the mall. And instead of coming back to pick her up, he simply says... honey, I am going to the office. When you are done shopping,  call the driver (+91-97415-xxxxx) and he would take you home.

NOTE >

  • As soon as the main thread calls the asynchronous method, his part is done
  • The callback method is executed on the ThreadPool thread
  • The call to BeginInvoke (so far... it has been something like... caller.BeginInvoke(25, out threadId, null, null);) would now have the 3rd parameter as an AsyncCallback which contains the callback method name.
  • The 4th parameter takes an object which your callback method might like to use
  • The ThreadPool threads are background threads. This means that they won't keep the application running in case the main thread ends. Thus, the main thread has to be alive for long enough to ensure that the background threads are done processing.

Let's take a look at the code (and read the comments to get a better understanding!).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Runtime.Remoting.Messaging;

namespace EventAndDelegateDemo
{
    //The delegate must have the same signature as the method. In this case,
    //we will make it same as TortoiseMethod
    public delegate string TortoiseCaller(int seconds, out int threadID);

    public class TortoiseClass
    {
        // The method to be executed asynchronously.
        public string TortoiseMethod(int seconds, out int threadID)
        {
            threadID = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("The slow method... executes...on thread {0}", Thread.CurrentThread.ManagedThreadId);
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(seconds / 5 * 1000);
                Console.WriteLine("The async task is going on thread # {0}", Thread.CurrentThread.ManagedThreadId);
            }
            return String.Format("I worked in my sleep for {0} seconds", seconds.ToString());
        }
    }

    //Now, that we are done with the declaration part, let's proceed to
    //consume the classes and see it in action
    //The algorithm would be very simple...
    //         1. Call delegate's BeginInvoke and pass the callback method's name
    //         2. Do some work on the main thread
    //         3. Your callback method is called when the processing completes. 
    //         4. Retrieve the delegate and call EndInvoke which won't be a blocking call this time!
    public class TortoiseConsumer
    {
        static void Main()
        {
            //Instantiate a new TortoiseClass
            TortoiseClass tc = new TortoiseClass();
            //Let's create the delegate now
            TortoiseCaller caller = new TortoiseCaller(tc.TortoiseMethod);

            //This is a dummy variable since this thread is not supposed to handle the callback anyways!!!
            int dummy = 0;
            //Start the asynchronous call with the following parameters...
            //Parameter 1 = 30 > In my example the tortoise class will now do something for 30 seconds
            //Parameter 2 = Dummy variable, just to get the output of the threadID
            //Parameter 3 = new AsyncCallback(CallbackMethod) > This is the method which would be called once the async task is over
            //Parameter 4 = Object > This is a string which would display the information about the async call
            IAsyncResult result = caller.BeginInvoke(30, out dummy,  new AsyncCallback(CallThisMethodWhenDone),
                "The call executed on thread {0}, with return value \"{1}\".");

            Console.WriteLine("The main thread {0} continues to execute...", Thread.CurrentThread.ManagedThreadId);

            //The callback method will use a thread from the ThreadPool.
            //But the threadpool threads are background threads. This implies that if you comment the line below
            //you would notice that the callback method is never called, since the background threads can't stop the main
            //program to terminate!
            Thread.Sleep(3000);
            Console.WriteLine("The main thread ends. Change the value 3000 in code to 40000 and see the result");
        }


        //The signature for the call back method must be same System.IAsyncResult delegate.
        static void CallThisMethodWhenDone(System.IAsyncResult ar)
        {
            //To retrieve the delegate we will cast the IAsyncResult to AsyncResult and get the caller
            AsyncResult result = (AsyncResult)ar;
            TortoiseCaller caller = (TortoiseCaller)result.AsyncDelegate;
            
            //Get the object (in our case it is just a format string) that was passed while calling BeginInvoke!  
            string formattedString = (string)ar.AsyncState;

            // Define a variable to receive the value of the out parameter.
            // If the parameter were ref rather than out then it would have to
            // be a class-level field so it could also be passed to BeginInvoke.
            //The following variable would take the Thread ID 
            int threadId = 0;

            //At this point, the threadID won't be a dummy variable as it was in the Main method
            //We are passing threadID to get the output from the TortoiseMethod
            string returnValue = caller.EndInvoke(out threadId, ar);

            //Use the format string to format the output message.
            Console.WriteLine(formattedString, threadId, returnValue);
        }
    }
}

 

There will be more on Delegates and Asynchronous programming going forward. 

转:http://www.dotnetscraps.com/dotnetscraps/post/Explaining-Delegates-in-C-Part-7-(Asynchronous-Callback-Way-4).aspx

转载于:https://www.cnblogs.com/shuaixf/p/3319245.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值