• 异步委托学习笔记


    异步委托就是定义一个方法,开一个新线程,让这个方法在后台执行。

    定义一个委托并异步调用它,是创建线程的一个简单方法。

    委托是方法的类型安全引用。Delegate类支持异步调用的方法,在后台Delegate类会创建一个执行任务的线程。

    我们先定义一个需要一定时间才能完成的方法:TakesAWhile(int data,int ms),这个方法调用Thread.Sleep方法,至少需要经过传入的参数ms毫秒后才能执行完。

    代码
    1. public static int TakesAWhile(int data,int ms)
    2. {
    3.     Console.WriteLine("TakesAWhile started");
    4.     Thread.Sleep(ms);
    5.     Console.WriteLine("\nTakesAWhile complated");
    6.     return ++data;
    7. }

    然后定义一个具有相同参数和返回类型的委托TakesAWhileDelegate(),如下所示:

    代码
    1. public delegate int TakesAWhileDelegate(int data,int ms);

    然后我们就可以使用不同的技术异步调用委托并返回结果。

    一、反复询问

    将方法交给后台执行后,我们仍可以检查委托的一些执行状态,如下面所示的是否完成(IsComplated)。

    所创建的Delegate类提供了BeginInvoke()方法,在该方法中可以传递用委托类型定义的输入参数。其返回类型为IAsyncResult。通过这个返回结果可以获得该委托的相关信息。下面是用了IsComplated方法检查委托是否完成,只要委托没有完成程序将一直执行:

     

    代码
    1. static void Main(string[] args)
    2. {
    3.     TakesAWhileDelegate t1 = TakesAWhile;
    4.     //将任务交给后台执行
    5.     IAsyncResult ar = t1.BeginInvoke(1, 9000, null, null);
    6.     //等待后台线程结束
    7.     while (!ar.IsCompleted)
    8.     {
    9.         Console.Write(".");
    10.         Thread.Sleep(50);
    11.     }
    12.     int result =t1.EndInvoke(ar);
    13.     //获取返回结果
    14.     Console.WriteLine("Result:{0}",result);
    15.     Console.ReadLine();
    16. }

    运行程序时,委托线程和主线程同时运行,委托线程完毕后,主线程的循环就停止了。同时也可以在主线程中调用EndInvoke方法结束后台线程。

    如果后台线程没有完成,EndInvoke方法会一直等待,知道后台线程完成或者主线程结束。

    二、等待一段时间后在询问

    等待异步委托的结果的另一种方法就是使用IAsyncReault相关联的等待句柄。使用AsyncWaitHandle属性就可以访问等待句柄。这个属性返回WaitHandle类型的对象,它可以等待委托线程完成其任务。WaitOne()方法将一个超时时间作为可选的第一个参数,在其中可以定义要等待的最长时间。如果发生超时WaitOne方法就返回false。

    代码
    1. static void Main(string[] args)
    2. {
    3.  
    4.     TakesAWhileDelegate t2 = TakesAWhile;
    5.     IAsyncResult ar = t2.BeginInvoke(1, 3000, null, null);
    6.     while (true)
    7.     {
    8.         Console.Write(".");
    9.         if (ar.AsyncWaitHandle.WaitOne(50,false))
    10.         {
    11.             Console.WriteLine("Can get the result now");
    12.             break;
    13.         }
    14.     }
    15.     int result = t2.EndInvoke(ar);
    16.     Console.WriteLine("Reault: {0}",result);
    17.     Console.ReadLine();
    18.  
    19. }

    这里,当检查到后台线程没有完成时,主线程不没有使用Thread.Sleep(50)这样的方法,可以去执行主线程中的其他任务。

    三、异步回调

    异步回调是指:将任务委托给后台一个线程,这个任务结束后,自动调用一个以定义的方法,而不需要在主线程中等待结果。

    在BeginInvoke()方法的第三个参数中,可以传递一个满足IAsyncCallback委托需要的方法。在该委托方法执行完之后,后台线程会调用这个方法,二不需要在主线程中等待后台线程的结果。

    IAsyncCallback委托定义了一个IAsyncResult类型的参数,其返回类型为void。以下的代码中,我们先定义一个TakesAWhileComplated()方法,用作回调方法。

    代码
    1. public static void TakesAWhileComplated(IAsyncResult ar)
    2. {
    3.     if (ar==null)
    4.     {
    5.         throw new ArgumentNullException("ar");
    6.     }
    7.     TakesAWhileDelegate t3 = ar.AsyncState as TakesAWhileDelegate;
    8.     Trace.Assert(t3 != null, "对象类型不对");
    9.     int result = t3.EndInvoke(ar);
    10.     Console.WriteLine("result {0}",result);
    11. }

    之后我们在主线程中启动这个方法:

    代码
    1. static void Main(string[] args)
    2. {
    3.     TakesAWhileDelegate t3 = TakesAWhile;
    4.     t3.BeginInvoke(1, 3000, TakesAWhileComplated, t3);
    5.     for (int i = 0; i < 100; i++)
    6.     {
    7.         Console.Write(".");
    8.         Thread.Sleep(50);
    9.     }
    10.  
    11.     Console.ReadLine();
    12. }

    运行这段代码,在控制台中就可以看见输出。

    这里只要TakesAWhileDelegate委托完成其任务,就会调用TakesAWhileComplated方法。不需要在主线程中等待结果。使用回调方法,必须注意这个方法从委托线程中调用,而不是从主线程中调用的。

    同时,在委托任务结束之前,不能停止主线程,除非主线程结束时停止的委托线程没有问题。

    本文代码下载:

    https://files.cnblogs.com/zyqgold/ConsoleApplication1.rar

    Technorati 标签: 异步委托
  • 相关阅读:
    1703技术笔录
    技术开发感想
    1701技术随笔
    12月份技术随笔
    光照效果函数
    冰冻效果
    反色效果函数
    哈哈镜效果
    黑白效果函数
    羽化效果
  • 原文地址:https://www.cnblogs.com/zyqgold/p/1966517.html
Copyright © 2020-2023  润新知