zoukankan      html  css  js  c++  java
  • 委托之异步

    在 使用BackgroundWorker组件 一文中,阐述了在Winform编程中,使用BackgroundWorker组件实现异步调用,本文主要讲述利用委托实现异步。

    以下描述摘抄于MSDN:

    异步委托提供以异步方式调用同步方法的能力。

    当同步调用委托时,Invoke()方法直接对当前线程调用目标方法;

    当异步调用委托时,CLR将对请求进行排队并立即返回到调用方,将对来自线程池的线程调用该目标方法,提交请求的原始线程继续与目标方法并行执行,该目标方法是对线程池线程运行的.

    1)、BeginInvoke()方法

    BeginInvoke()方法启动异步调用,它与需要异步执行的方法具有相同的参数。

    另外,还有两个可选参数:第一个参数是AsyncCallback委托,该委托引用在异步调用完成时要调用的方法;第二个参数是用户定义的对象,该对象可向回调方法传递信息;

    BeginInvoke立即返回,不等待异步调用完成;

    BeginInvoke返回IAsyncResult,这个结果可用于监视异步调用的进度;

    2)、EndInvoke()方法

    EndInvoke()方法检索异步调用的结果;

    在调用BeginInvoke()方法后,可以随时调用EndInvoke()方法,如果异步调用尚未完成,则EndInvoke()方法将一直阻止调用线程,直到异步调用完成后才允许调用线程执行;

    EndInvoke()的参数需要异步执行的方法的out和ref参数以及由BeginInvoke()返回的IAsyncResult。

    下面通过代码阐述异步委托:

    代码一,同步执行:
     public delegate int MathDelegate(int x);    
    public class MathClass
    {
    public int Add(int x)
    {
    Thread.Sleep(10000);//此处模拟长时间执行的任务
    return x + x;
    }
    }

    public class Program
    {
    public static void Main(string[] args)
    {
    MathClass addClass = new MathClass();
    MathDelegate mathDel = new MathDelegate(addClass.Add);

    //同步执行
    int syncResult = mathDel(8);
    Console.WriteLine("Sync Proccessing operation...");//这一行只有SyncMethod完成以后才能显示
    Console.WriteLine("Sync Result is: {0}", syncResult);

    Console.ReadLine();
    }
    }
    当程序执行到 int syncResult = mathDel(8); 的时候,主线程将等待至少10秒的时间(Add方法的执行),才能执行
    后面的代码,也即在期间,应用程序没有响应,不能执行其他的任何操作,直到Add方法返回结果。
    代码二,异步执行:

    我们稍微修改一下Main的代码:

    public static void Main(string[] args)
    {
    MathClass addClass = new MathClass();
    MathDelegate mathDel = new MathDelegate(addClass.Add);

    IAsyncResult async = mathDel.BeginInvoke(9, null, null);//在另外的线程里,调用Add方法
    Console.WriteLine("Async Proccessing operation...");//立即打印到终端设备
    int asyncReuslt = mathDel.EndInvoke(async);
    Console.WriteLine("Result is: {0}", asyncReuslt);

    Console.ReadLine();
    }

    在这段代码中,在开始并没有直接调用方法,而是使用BeginInvoke()方法,返回IAsyncResult 对象。

    代码三,IsCompleted,轮询异步调用完成
    使用IAsyncResult实例的IsCompleted属性,以获取异步操作是否已完成的指示,如果操作完成则为True,否则为False。

    修改一下Main的代码:

    public static void Main(string[] args)
    {
    MathClass addClass = new MathClass();
    MathDelegate mathDel = new MathDelegate(addClass.Add);

    IAsyncResult async = mathDel.BeginInvoke(9, null, null);//在另外的线程里,调用Add方法
    Console.WriteLine("Async Proccessing operation...");//立即打印到终端设备

    int i = 1;
    while (async.IsCompleted==false)
    {
    Thread.Sleep(i * 1000);
    Console.WriteLine("IsCompleted:{0},{1}", async.IsCompleted, i);
    i++;
    }
    int asyncReuslt = mathDel.EndInvoke(async);
    Console.WriteLine("Result is: {0}", asyncReuslt);

    Console.ReadLine();
    }
    代码四,AsyncCallback,异步调用完成时执行回调方法

    如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法;

    如果要使用回调方法,必须将引用回调方法AsyncCallback委托传递给BeginInvoke()方法,也可以传递包含回调方法将要使用的信息的对象。

    修改一下Main的代码:

    public static void Main(string[] args)
    {
    MathClass addClass = new MathClass();
    MathDelegate mathDel = new MathDelegate(addClass.Add);

    IAsyncResult async = mathDel.BeginInvoke(9, new AsyncCallback(CompleteMethod), "信息来自于主线程");//在另外的线程里,调用Add方法
    Console.WriteLine("Async Proccessing operation...");//立即打印到终端设备
    Console.ReadLine();
    }
    private static void CompleteMethod(IAsyncResult async)
    {
    AsyncResult ar = (AsyncResult)async;

    MathDelegate del = (MathDelegate)ar.AsyncDelegate;
    int result = del.EndInvoke(async);

    string mainTheadMsg = ar.AsyncState as string;
    Console.WriteLine("{0}, Result is: {1}", mainTheadMsg, result);
    }
    Add方法调用完成以后,调用 CompleteMethod 方法
  • 相关阅读:
    EntityFramework 启用迁移 EnableMigrations 报异常 "No context type was found in the assembly"
    JAVA 访问FTP服务器示例(2)
    NuGet Package Manager 更新错误解决办法
    JAVA 访问FTP服务器示例(1)
    RemoteAttribute 的使用问题
    诡异的 javascript 变量
    javascript apply用法
    Babun 中文乱码
    GSM呼叫过程
    转站博客园
  • 原文地址:https://www.cnblogs.com/wangchuang/p/3670417.html
Copyright © 2011-2022 走看看