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

    In this part of making asynchronous programming with delegates, we will talk about a different way, which is a little better than Way 1. In the previous post, it was like a husband telling his wife...

    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 Winking. In the meantime, I will take care of some other stuff. As soon as I am done, I promise I will pick you up.

    Notice that, although it looks like a good way of getting the work done, it has a tiny flaw (not really a flaw, but I will still call it a flaw to make my story!). What if their 6 year old kid called the husband in the meantime? Would the husband appreciate it while waiting he can do nothing else but wait? I mean, what if he has to just pick up the phone and tell his child, you know kiddo, I am here at the mall waiting for your mom. I'll be back in some time! This example just does that. Basically, we know that EndInvoke is a blocking call. If you make this call, you can do nothing but wait, which may make your UI look awful. In this example, we will be waiting for the async call to complete, but still be free enough to do some stuff.

    Okay, enough said... let's take a look at the code (in fact, it is always better to run it!!!)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Diagnostics;
    
    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 thread # {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 result's AsyncWaitHandle.WaitOne() which would be a blocking call
        //         4. Call EndInvoke which won't be a blocking call this time!
        //         5. Close the result's AsyncWaitHandle, explicitly.
        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);
                //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);
                //After calling the method asynchronously, the main thread continues to work...
                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 = 10; i > 1; i--)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine("{0}...", i);
                }
                Stopwatch s = new Stopwatch();
                //Calling WaitOne is a blocking call. As soon as you call WaitOne, you won't proceed further
                //in this main thread until the Async call completes
                Console.WriteLine("Before calling WaitOne... {0} milliseconds", s.ElapsedMilliseconds.ToString());
                s.Start();
                //The next call can be a blocking call (in our case it WILL be a blocking call since the Tortoise
                //method takes 30 seconds to complete. By now, already 12 seconds are over!
                result.AsyncWaitHandle.WaitOne(2000);
                //The good thing is that, now you can do update the client while still waiting for the call to complete
                Console.WriteLine("Well, I know waiting could be boring, but at the moment I am still waiting...");
                //Waiting for 5 seconds now!
                result.AsyncWaitHandle.WaitOne(5000);
                //Updating once again...
                Console.WriteLine("Argghh... when will this end??");
                //Waiting till the async call is complete (Notice that this can be blocking!!)
                result.AsyncWaitHandle.WaitOne();
                s.Stop();
                Console.WriteLine("After calling WaitOne... {0} milliseconds", s.ElapsedMilliseconds.ToString());
                //Notice that this call will NOT be a blocking call as it was in our previous example!
                string returnValue = caller.EndInvoke(out threadId, result);
                //Close the wait handle. This is important, since it is not automatically cleared.
                //Only the next GC can collect this native handle. So, it is a good practise to clear
                //this handle as soon as you are done with it.
                result.AsyncWaitHandle.Close();
                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-5-(Asynchronous-Callback-Way-2).aspx

  • 相关阅读:
    JAVA自学笔记13
    非常不错的一款打字代码效果
    诡异的python文件
    Linux 虚拟机 docker 上 搭建 python 机器学习 平台
    git无法pull仓库: refusing to merge unrelated histories
    Python
    28 Jupyter Notebook tips, tricks, and shortcuts[Re-post]
    What is the best way to calculate a checksum for a file that is on my machine?
    Building MAPI Applications on 32-Bit and 64-Bit Platforms
    Linux 查看进程 关闭进程
  • 原文地址:https://www.cnblogs.com/shuaixf/p/3319213.html
Copyright © 2011-2022 走看看