• 异步编程模型使用 IAsyncResult 对象


    先推荐阅读下面的资料:

    MSDN:异步编程设计模式

    IBM developerworks: 使用异步 I/O 大大提高应用程序的性能

    参考博文:

    1、正确使用异步操作 

    2、Lab:体会ASP.NET异步处理请求的效果

    3、WCF中的异步调用

    4、WCF从理论到实践(11)-异步

    5、异步编程

    .NET Framework 为异步操作提供两种设计模式:
    1、使用 IAsyncResult 对象的异步操作。
    2、使用事件的异步操作。

    IAsyncResult接口类型

        [ComVisible(true)]
        
    public interface IAsyncResult
        {
            
    // 摘要:
            
    //     获取用户定义的对象,它限定或包含关于异步操作的信息。
            
    //
            
    // 返回结果:
            
    //     用户定义的对象,它限定或包含关于异步操作的信息。
            object AsyncState { get; }
            
    //
            
    // 摘要:
            
    //     获取用于等待异步操作完成的 System.Threading.WaitHandle。
            
    //
            
    // 返回结果:
            
    //     用于等待异步操作完成的 System.Threading.WaitHandle。
            WaitHandle AsyncWaitHandle { get; }
            
    //
            
    // 摘要:
            
    //     获取异步操作是否同步完成的指示。
            
    //
            
    // 返回结果:
            
    //     如果异步操作同步完成,则为 true;否则为 false。
            bool CompletedSynchronously { get; }
            
    //
            
    // 摘要:
            
    //     获取异步操作是否已完成的指示。
            
    //
            
    // 返回结果:
            
    //     如果操作完成则为 true,否则为 false。
            bool IsCompleted { get; }
        }


    下面是使用 IAsyncResult 对象的测试代码。

     public delegate string AsyncDelegate(int callDuration, out int threadId);
        
    class Program
        {
            
    static void Main(string[] args)
            {
                Fun1();
                Console.ReadLine();
            }

            
    private static int threadId;

            
    //阻塞等待   使用 EndInvoke 等待异步调用  
            static void Fun1()
            {
                
    //创建示例类的实例。
                AsyncDemo ad = new AsyncDemo();
                
    // 创建委托
                AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
                
    // 委托在这里开始异步调用。
                IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, nullnull);
                
    //人为的线程阻塞。
                Thread.Sleep(0);
                Console.WriteLine(
    "主线程 {0}开始工作",Thread.CurrentThread.ManagedThreadId);
                
    // 委托开始EndInvoke调用,这个过程会使主线程等待异步调用完成并返回结果。
                string ret = dlgt.EndInvoke(out threadId, ar);
                Console.WriteLine(
    "异步线程 {0},返回值 \"{1}\".", threadId, ret);
                Console.WriteLine(
    "主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
            }
            
            
    //阻塞等待  使用 WaitHandle 等待异步调用
            static void Fun2()
            {
                AsyncDemo ad 
    = new AsyncDemo();
                AsyncDelegate dlgt 
    = new AsyncDelegate(ad.TestMethod);
                IAsyncResult ar 
    = dlgt.BeginInvoke(5000,out threadId, nullnull);
                Thread.Sleep(
    0);
                Console.WriteLine(
    "主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
                
    //主线程在这里等待,直到异步线程执行完。
                ar.AsyncWaitHandle.WaitOne();
                
    // 和前一方案的区别在于,你可以在异步调用完成后,获取异步调用返回值之前
                
    //在这里做点任何你想作的事。
                
    //调用EndInvoke获取异步调用的返回结果.
                string ret = dlgt.EndInvoke(out threadId, ar);
                Console.WriteLine(
    "异步线程 {0},返回值 \"{1}\".", threadId, ret);
                Console.WriteLine(
    "主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
            }

            
    //轮询状态    轮询异步调用完成
            static void Fun3()
            {
                AsyncDemo ad 
    = new AsyncDemo();
                AsyncDelegate dlgt 
    = new AsyncDelegate(ad.TestMethod);
                IAsyncResult ar 
    = dlgt.BeginInvoke(5000,out threadId, nullnull);
                Console.WriteLine(
    "主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
                
    //这里每隔10毫秒就检测(轮询)一下异步执行的状态,
                
    //直到异步调用完成,IsCompleted的值变为ture为止。
                while (ar.IsCompleted == false)
                {
                    Thread.Sleep(
    10);
                }

                
    //还记得微软的那个善意的提醒吗?虽然IsCompleted为true了,
                
    //我们还是调用一下EndInvoke,来获取返回值。
                string ret = dlgt.EndInvoke(out threadId, ar);
                Console.WriteLine(
    "异步线程 {0},返回值 \"{1}\".", threadId, ret);
                Console.WriteLine(
    "主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
            }

            
    //通知机制    异步调用完成时执行回调方法
            static void Fun4()
            {
                AsyncDemo ad 
    = new AsyncDemo();
                AsyncDelegate dlgt 
    = new AsyncDelegate(ad.TestMethod);
                
    //注意第三个参数,这就是我们要用到的回调方法。
                
    //第四个参数更为有趣,它可以是任何Object对象,这里它就是
                
    //执行异步调用的委托本身,把委托本身传递进去的原因在下面可以看到。
                Console.WriteLine("主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
                IAsyncResult ar 
    = dlgt.BeginInvoke(5000,out threadId, new AsyncCallback(CallbackMethod), dlgt);
                Console.WriteLine(
    "主线程 {0}结束工作", Thread.CurrentThread.ManagedThreadId);
                Console.ReadLine();
            }
            
    //回调函数必须严格的遵照AsyncCallback委托的签名。
            static void CallbackMethod(IAsyncResult ar)
            {
                
    //在这里,上面那个dlgt作为参数的作用得到了体现,原来它就是为了完成对EndInvoke的调用啊。
                AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState;
                
    //通过对EndInvoke的调用获取返回值。
                string ret = dlgt.EndInvoke(out threadId, ar);
                Console.WriteLine(
    "异步线程 {0},返回值 \"{1}\".", threadId, ret);
            }
        }
        
    //使用异步编程模型 
        public class AsyncDemo
        {
            
    public string TestMethod(int callDuration, out int threadId)
            {
                Console.WriteLine(
    "异步方法开始工作");
                Thread.Sleep(callDuration);
                threadId 
    = Thread.CurrentThread.ManagedThreadId; 
                
    return "异步方法执行时间 " + callDuration.ToString();
            }
        }

     执行结果:

    Fun1--------------------

    异步方法开始工作
    主线程 10开始工作
    异步线程 7,返回值 "异步方法执行时间 5000".
    主线程10结束工作
    Fun2---------------------
    异步方法开始工作
    主线程 10开始工作
    异步线程 7,返回值 "异步方法执行时间 5000".
    主线程10结束工作
    Fun3---------------------

    主线程 10开始工作
    异步方法开始工作
    异步线程 7,返回值 "异步方法执行时间 5000".
    主线程10结束工作
    Fun4---------------------
    主线程 10开始工作
    主线程 10结束工作
    异步方法开始工作
    异步线程 7,返回值 "异步方法执行时间 5000".
    --------------------------

    工作当中有一个调用ActiveMQ的产品,每天大概是上万的消息。压力也不是很大。最近总是出现调用MQ阻塞的情况。负责MQ的同事也没有找到原因。

    我是想寻找一个消息队列的代替品。 上面的第四个方法,异步线程不阻塞调用线程,当然调用线程也无需处理调用结果,貌似可以作为一个代替方案。


  • 相关阅读:
    duilib设置背景颜色透明度
    Centos7 源码编译安装cmake 3.15
    SecureCRT修改背景主题和背景颜色
    fopen的最后一个参数说明
    SFTP从windows上传到linux服务器命令
    小白html 第一个网页
    linux上编译nginx 实现网页开发
    duilib list item互换
    libcurl 错误CURLE_COULDNT_CONNECT 解决办法
    使用mshta.exe绕过应用程序白名单
  • 原文地址:https://www.cnblogs.com/tenghoo/p/ARM_IAsyncResult.html
Copyright © 2020-2023  润新知