• C#中的异步调用及异步设计模式(一)


    近期项目中使用了不少异步操作,关于“异步”做个总结。总结的内容大部分都来自于MSDN,还有一些自己的心得。

    关于“异步”的使用可分为:使用层面和类库设计层面,细分如下:

    一、使用异步方式调用同步方法(使用层面)。

    二、使用 IAsyncResult 调用异步方法(使用层面)。

    三、基于 IAsyncResult 的异步设计模式(设计层面)。

    四、基于事件的异步模式(设计层面)。

    关于上述异步编程的几个方面,下面分别做以详述。

    一、使用异步方式调用同步方法(使用层面)

    .NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。BeginInvoke 方法可启动异步调用,EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。

    该调用方式是使用委托进行异步调用,其实质是:调用“BeginInvoke”方法,公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是在线程池线程运行的。

    在异步调用启动后,在等待异步调用结果的时候,可以进行以下四种方法。

    ·                     进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。

    1. using System;  
    2. using System.Threading;  
    3.   
    4. namespace Examples.AdvancedProgramming.AsynchronousOperations  
    5. {  
    6.     public class AsyncMain  
    7.     {  
    8.         public static void Main()  
    9.         {  
    10.             // The asynchronous method puts the thread id here.  
    11.             int threadId;  
    12.   
    13.             // Create an instance of the test class.  
    14.             AsyncDemo ad = new AsyncDemo();  
    15.   
    16.             // Create the delegate.  
    17.             AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);  
    18.   
    19.             // Initiate the asychronous call.  
    20.             IAsyncResult result = caller.BeginInvoke(3000,  
    21.                 out threadId, null, null);  
    22.   
    23.             Thread.Sleep(0);  
    24.             Console.WriteLine("Main thread {0} does some work.",  
    25.                 Thread.CurrentThread.ManagedThreadId);  
    26.   
    27.             // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。  
    28.             string returnValue = caller.EndInvoke(out threadId, result);  
    29.   
    30.             Console.WriteLine("The call executed on thread {0}, with return value "{1}".",  
    31.                 threadId, returnValue);  
    32.         }  
    33.     }  
    34. }  


     

    ·                     进行某些操作,然后使用 IAsyncResult..::.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne 方法(该方法可以设置一个超时时间)一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。

    1. using System;  
    2. using System.Threading;  
    3.   
    4. namespace Examples.AdvancedProgramming.AsynchronousOperations  
    5. {  
    6.     public class AsyncMain  
    7.     {  
    8.         static void Main()  
    9.         {  
    10.             // The asynchronous method puts the thread id here.  
    11.             int threadId;  
    12.   
    13.             // Create an instance of the test class.  
    14.             AsyncDemo ad = new AsyncDemo();  
    15.   
    16.             // Create the delegate.  
    17.             AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);  
    18.   
    19.             // Initiate the asychronous call.  
    20.             IAsyncResult result = caller.BeginInvoke(3000,  
    21.                 out threadId, null, null);  
    22.   
    23.             Thread.Sleep(0);  
    24.             Console.WriteLine("Main thread {0} does some work.",  
    25.                 Thread.CurrentThread.ManagedThreadId);  
    26.   
    27.             // 调用此方法将会一直等待异步操作完成,并阻塞当前线程。  
    28.             result.AsyncWaitHandle.WaitOne();  
    29.   
    30.             // Perform additional processing here.  
    31.             // Call EndInvoke to retrieve the results.  
    32.             string returnValue = caller.EndInvoke(out threadId, result);  
    33.   
    34.             Console.WriteLine("The call executed on thread {0}, with return value "{1}".",  
    35.                 threadId, returnValue);  
    36.         }  
    37.     }  
    38. }  


     

    ·                     进行某些操作,然后轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。

    1. using System;  
    2. using System.Threading;  
    3.   
    4. namespace Examples.AdvancedProgramming.AsynchronousOperations  
    5. {  
    6.     public class AsyncMain  
    7.     {  
    8.         static void Main()  
    9.         {  
    10.             // The asynchronous method puts the thread id here.  
    11.             int threadId;  
    12.   
    13.             // Create an instance of the test class.  
    14.             AsyncDemo ad = new AsyncDemo();  
    15.   
    16.             // Create the delegate.  
    17.             AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);  
    18.   
    19.             // Initiate the asychronous call.  
    20.             IAsyncResult result = caller.BeginInvoke(3000,  
    21.                 out threadId, null, null);  
    22.   
    23.             // 等待结果返回  
    24.             while (result.IsCompleted == false)  
    25.             {  
    26.                 Thread.Sleep(10);  
    27.             }  
    28.   
    29.             // Call EndInvoke to retrieve the results.  
    30.             string returnValue = caller.EndInvoke(out threadId, result);  
    31.   
    32.             Console.WriteLine("The call executed on thread {0}, with return value "{1}".",  
    33.                 threadId, returnValue);  
    34.         }  
    35.     }  
    36. }  


     

    ·                     将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 ThreadPool 线程上执行该方法。该回调方法将调用 EndInvoke。注意:该回调函数的执行是在另外一个线程上。

     

    1. using System;  
    2. using System.Threading;  
    3.   
    4. namespace Examples.AdvancedProgramming.AsynchronousOperations  
    5. {  
    6.     public class AsyncMain   
    7.     {  
    8.         // Asynchronous method puts the thread id here.  
    9.         private static int threadId;  
    10.   
    11.         static void Main() {  
    12.             // Create an instance of the test class.  
    13.             AsyncDemo ad = new AsyncDemo();  
    14.   
    15.             // Create the delegate.  
    16.             AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);  
    17.   
    18.             // Initiate the asychronous call.  Include an AsyncCallback  
    19.             // delegate representing the callback method, and the data  
    20.             // needed to call EndInvoke.  
    21.             IAsyncResult result = caller.BeginInvoke(3000,  
    22.                 out threadId,   
    23.                 new AsyncCallback(CallbackMethod),  
    24.                 caller );  
    25.   
    26.             Console.WriteLine("Press Enter to close application.");  
    27.             Console.ReadLine();  
    28.         }  
    29.   
    30.         // Callback method must have the same signature as the  
    31.         // AsyncCallback delegate.  
    32.         static void CallbackMethod(IAsyncResult ar)   
    33.         {  
    34.             // Retrieve the delegate.  
    35.             AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;  
    36.   
    37.             // Call EndInvoke to retrieve the results.  
    38.             string returnValue = caller.EndInvoke(out threadId, ar);  
    39.   
    40.             Console.WriteLine("The call executed on thread {0}, with return value "{1}".",  
    41.                 threadId, returnValue);  
    42.         }  
    43.     }  
    44. }  


    二、使用 IAsyncResult 调用异步方法(使用层面)

    .NET Framework 的许多方面都支持异步编程功能,这些方面包括:

    ·                     文件 IO、流 IO、套接字 IO。

    ·                     网络。

    ·                     远程处理信道(HTTP、TCP)和代理。

    ·                     使用 ASP.NET 创建的 XML Web services。

    ·                     ASP.NET Web 窗体。

    ·                     使用 MessageQueue 类的消息队列。

    这些已经实现了异步操作的类或组件,可以直接调用其异步方法(以Begin和End开头)。调用异步方法后等待结果可以参考“异步调用同步方法”的处理。

     

    三、基于 IAsyncResult 的异步设计模式(设计层面)

    待续...

  • 相关阅读:
    EF4.1中诡异的GUID为空问题
    asp.net mvc3 Razor引擎中@使用规则小记
    【推荐】JS面象对象编程视频教程
    【转】【More Effective C#】IEnumerable和IQueryable的那点事
    【你有更好的算法吗?】合并重叠时间段算法
    jquery处理textarea中的手动换行
    实例讲解遗传算法——基于遗传算法的自动组卷系统【理论篇】
    架设自己的NuGet服务器
    C#中用SelectSingleNode方法解析带有多个命名空间的XML文件
    解析入口参数为实体的表达式树
  • 原文地址:https://www.cnblogs.com/zhaoxinshanwei/p/3878499.html
Copyright © 2020-2023  润新知