• Explaining Delegates in C#


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

    Callback and Multicast delegates
    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

  • 相关阅读:
    创建进程
    进程
    操作系统历史
    socket
    网络基础
    常用模块二:hashlib、configparser、logging
    常见正则匹配
    类中的内置方法(魔法方法、双下方法)
    反射、isinstance和issubclass
    封装、继承、多态
  • 原文地址:https://www.cnblogs.com/shuaixf/p/3319245.html
Copyright © 2020-2023  润新知