zoukankan      html  css  js  c++  java
  • C#多线程编程之:异步方法调用

    异步方法

      当一个线程调用方法后,直到方法执行完毕,线程才继续执行,这种方法被称为同步方法。然而,有些方法执行时间可能非常长,比如串口操作或访问网络,这样线程被阻塞,而无法响应用户的其他请求。这种情况通常是无法忍受的,所以这时我们应该使用异步方法。

      异步方法的原理是,在方法调用前为异步方法指定一个回调函数,方法调用后被线程池中的一个线程接管,执行该方法。主线程立即返回,继续执行其他工作或响应用户请求。如果异步方法执行完毕,回调函数被自动执行,以处理异步方法的调用结果。

      如何实现异步方法呢?C#通过异步委托调用BeginInvoke和EndInvoke方法来实现异步方法。

    BeginInvoke方法原型:

      IAsyncResult BeginInvoke(......, AsyncCallback callback, object o);
      ......表示异步委托中定义的参数列表。
      AsyncCallback参数是一个用于回调函数的委托,它的原型为:
      public delegate void AsyncCallback(IAsyncResult ar)。其中IAsyncResult参数用于包装异步方法的执行结果。
      Object参数用于在主线程与回调函数间传递一些附加信息,如同步信息。

    EndInvoke方法原型:

      xxx EndInvoke(IAsyncResult result);
      xxx表示异步委托原型中定义的返回数据类型,IAsyncResult用于包装异步方法的执行结果。

      这么看着是不是有点迷糊?看个例子就明白了:

    复制代码
    using System;
    using System.Threading;
    using System.Runtime.Remoting.Messaging;

    namespace ProcessTest
    {
    class Program
    {
    //异步调用执行完成同步信号
    static AutoResetEvent ev =new AutoResetEvent(false);
    //定义委托
    publicdelegateint Deleg(int a, int b);

    staticint WriteSum(int a, int b)
    {
    //显示当前线程ID号及Sum值
    Console.WriteLine("执行WriteSum的线程ID为:{0},Sum = {1}", Thread.CurrentThread.ManagedThreadId, a + b);
    return a + b;
    }

    //回调函数
    staticvoid SumDone(IAsyncResult async)
    {
    //等待1秒,模拟线程正在执行其他工作
    Thread.Sleep(1000);

    //async中包装了异步方法执行的结果
    //从操作结果async中还原委托
    Deleg proc = ((AsyncResult)async).AsyncDelegate as Deleg;
    //获取异步方法的执行结果
    int sum = proc.EndInvoke(async);

    //显示结果
    Console.WriteLine("执行SumDone的线程ID为:{0},Sum = {1}", Thread.CurrentThread.ManagedThreadId, sum);

    //使用AsnycState属性获取主线程中传入的同步信号
    //释放同步信号表示异步调用已完成
    ((AutoResetEvent)async.AsyncState).Set();


    }

    staticvoid Main(string[] args)
    {
    //创建一个委托
    Deleg proc =new Deleg(WriteSum);

    //采用异步方式调用委托
    //指定SumDone为异步操作完成后的回调函数
    //指定ev为object参数,用于同步回调函数与主线程间操作
    IAsyncResult async = proc.BeginInvoke(10, 10, SumDone, ev);
    Console.WriteLine(
    "主线程ID号为:{0},异步操作已开始执行,正等待操作完成。", Thread.CurrentThread.ManagedThreadId);

    //等待异步操作完成
    ev.WaitOne();
    Console.WriteLine(
    "异步操作已完成!");

    System.Console.ReadKey();
    }
    }
    }
    复制代码

     

      下图是程序的运行结果:

      

      注意观察运行结果,异步方法和回调函数是在同一步线程执行。

    为方法指定OneWay特性

      我们可将 System.Runtime.Remoting.Messaging.OneWay特性应用于任何一个方法,该特性告诉CLR该方法不返回任何信息。即 使该方法实际返回了数据(通过return语句或out、ref定义的参数),但只要被标记了OneWay特性,那它就不会再返回任何信息。

      一个被标记为OneWay特性的方法即可以同步方式调用,也可以异步方式调用。如果在它的执行过程中引起了一个异常却没有捕获,在同步方式下,该异常会向上传播;但在异步方式下,该异常将不会被传播。大多数情况下,被标记为OneWay的方法是以异步方式工作。

  • 相关阅读:
    查看windows以前连过的wifi密码
    winscp可能的替代品?
    查看windows的进程启动参数
    Ubuntu Server 安全补丁、版本升级
    AtCoder Beginner Contest 217 题解
    F. Alice and Recoloring 1&2
    E. Bored Bakry
    C. Bakry and Partitioning
    2021牛客多校 第四场
    AES解密报Given final block not properly padded
  • 原文地址:https://www.cnblogs.com/mili3/p/3737482.html
Copyright © 2011-2022 走看看