zoukankan      html  css  js  c++  java
  • Explaining Delegates in C#

    So far, I have discussed about Callback, Multicast delegatesEvents using delegates, and yet another example of events using delegates. In this post, I will take this topic one step forward and show you an example of Asynchronous callbacks using delegates.

    Let's say a client calls a method that takes 40 minutes to complete, how do we communicate with the client?

    Option 1> Keep showing that busy Cursor for 40 minutes!!!

    Option 2> Keep updating the client with appropriate messages, like... "oh yes... we might take another light year to complete, please wait... oh common..... show some patience... do yoga... etc...  etc...."

    Option 3> Tell the client that "okay Sir... you are done with your part... go away take a vacation. Whenever I'm done I will let you know"

    As you may agree... Option 3 is a more effective way. Not because it gives you enough time to complete your job , but because the client is not just waiting on you. He is gone after giving you the job and may be doing something else in life. HE is FREE... and FREEDOM is good 

    Before we proceed, let's see what happened to the delegate from my previous post (in ILDASM)...

    Take a look in the figure above and notice that just creating the delegate in your code, actually created a class behind the scenes with a few methods called Invoke, BeginInvoke, and EndInvoke!!!!! Pretty smart, right?

    <Snippet from MSDN>

    Delegates enable you to call a synchronous method in an asynchronous manner. When you call a delegate synchronously, the Invoke method calls the target method directly on the current thread. If the BeginInvoke method is called, the common language runtime (CLR) queues the request and returns immediately to the caller. The target method is called asynchronously on a thread from the thread pool. The original thread, which submitted the request, is free to continue executing in parallel with the target method. If a callback method has been specified in the call to the BeginInvoke method, the callback method is called when the target method ends. In the callback method, the EndInvoke method obtains the return value and any input/output or output-only parameters. If no callback method is specified when calling BeginInvoke, EndInvoke can be called from the thread that called BeginInvoke.

    </Snippet from MSDN>

    Asynchronous calls has two important parts... BeginInvoke and EndInvoke. Once BeginInvoke is called, EndInvoke can be called anytime. The catch is that EndInvoke is a blocking call. Thus, it would block the calling thread until it is complete. There are several ways in which you could work with BeginInvoke and EndInvoke at tandem. In this post we will take a look at the first way!!

    The following code is almost like a husband telling his wife (whom he is dropping in a mall for some shopping!!)...

    You know honey, I have a lot of work to do. Why don't you help me up by doing something that you can do pretty well . In the meantime, I will take care of some other stuff. As soon as I am done, I promise I will pick you up.

    The good thing with this approach is that the wife (in our case, a new thread) is doing something, while the main thread can continue to do something else. The catch is that, the husband (main thread) must be aware that once its job is done, it will have to wait (blocking call) for his wife (the other thread)!! Just like I do, well... almost always 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    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)
            {
                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... {0}", Thread.CurrentThread.ManagedThreadId);
                }
                threadId = 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
        //         2. Do some work on the main thread
        //         3. Call the delegate's EndInvoke
        public class TortoiseConsumer
        {
            public static void Main()
            {
                //Instantiate a new TortoiseClass
                TortoiseClass tc = new TortoiseClass();
                //Let's create the delegate now
                TortoiseCaller caller = new TortoiseCaller(tc.TortoiseMethod);
                //The asynchronous method puts the thread id here
                int threadId;
                //Make the async call. Notice that this thread continues to run after making this call
                Console.WriteLine("Before making the Async call... Thread ID = {0}", Thread.CurrentThread.ManagedThreadId);
                IAsyncResult result = caller.BeginInvoke(30, out threadId, null, null);
                Console.WriteLine("After making the Async call... Thread ID = {0}", Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("Perform more work as the other thread works...");
                for (int i = 30; i > 1; i--)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine("{0}...", i);                                
                }
                Console.WriteLine("Waiting for the async call to return now...");
                //Notice that this call will be a blocking call
                string returnValue = caller.EndInvoke(out threadId, result);
                Console.WriteLine("The call got executed on thread {0}", threadId);
                Console.WriteLine("The value returned was - {0}", returnValue);
            }
        }
    }

    I will discuss about more ways of doing asynchronous programming in some of my next posts.

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

  • 相关阅读:
    【Spring】注解的循环依赖问题
    【网络】计算机网络自顶向下读书笔记
    【JUC】并发编程的艺术笔记
    【JUC】多线程手撕代码面试题
    【操作系统】王道操作系统全盘汇总
    【Spring】IoC源码分析以及实现
    【Spring】用例子来初次理解IoC
    拼音工具类
    chr(10)与chr(13)的区别
    List 集合转String 逗号拼接
  • 原文地址:https://www.cnblogs.com/shuaixf/p/3319200.html
Copyright © 2011-2022 走看看