常见异步机制分析

本章内容:

  1、使用 EndInvoke 等待异步调用

  2、使用 WaitHandle 等待异步调用

  3、轮询状态    轮询异步调用完成

  4、通知机制    异步调用完成时执行回调方法

  异步操作通常用于执行完成时间可能较长的任务,避免阻塞,这是与线程有所相似的地方,具体异同自行百度吧,推荐《多线程与异步的区别》这篇文章,讲得很好。

  

创建我们使用到的模型和委托

public delegate string AsyncDele(int callDuration, out int threadId);

//使用异步编程模型
    public class AsyncDemoModel
    {
        public string TestMethod(int callDuration, out int threadId)
        {
            Console.WriteLine("异步方法开始工作");
            Thread.Sleep(callDuration);
            threadId = Thread.CurrentThread.ManagedThreadId;
            return "异步方法执行时间 " + callDuration.ToString();
        }
    }

1、使用 EndInvoke 等待异步调用

   static void Func1()
        {
            AsyncDemoModel ad = new AsyncDemoModel();
            // 创建委托
            AsyncDele dlgt = new AsyncDele(ad.TestMethod);
            // 委托在这里开始异步调用。
            IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null);
            //人为的线程阻塞。
            Thread.Sleep(1000);
            Console.WriteLine("主线程 {0}开始工作",Thread.CurrentThread.ManagedThreadId);
            // 委托开始EndInvoke调用,这个过程会使主线程等待异步调用完成并返回结果。
            Console.WriteLine("使用 EndInvoke 等待异步调用!!!");
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine("异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine("主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }

2、使用 WaitHandle 等待异步调用

 static void Func2()
        {
            AsyncDemoModel ad = new AsyncDemoModel();
            AsyncDele dlgt = new AsyncDele(ad.TestMethod);
            IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null);
            Thread.Sleep(0);
            Console.WriteLine("主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
            //主线程在这里等待,直到异步线程执行完。
            Console.WriteLine("使用 WaitHandle 等待异步调用!!!");
            ar.AsyncWaitHandle.WaitOne();
            // 和前一方案的区别在于,你可以在异步调用完成后,获取异步调用返回值之前
            Console.WriteLine("和前一方案的区别在于,你可以在异步调用完成后,获取异步调用返回值之前");
            //在这里做点任何你想作的事。
            //调用EndInvoke获取异步调用的返回结果.
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine("异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine("主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }

3、轮询

   static void Func3()
        {
            AsyncDemoModel ad = new AsyncDemoModel();
            AsyncDele dlgt = new AsyncDele(ad.TestMethod);
            IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null);
            Console.WriteLine("使用轮询异步调用!!!");
            Console.WriteLine("主线程 {0}开始工作", Thread.CurrentThread.ManagedThreadId);
            //这里每隔10毫秒就检测(轮询)一下异步执行的状态,
            //直到异步调用完成,IsCompleted的值变为ture为止。
            while (ar.IsCompleted == false)
            {
                Thread.Sleep(10);
            }
            //还是调用一下EndInvoke,来获取返回值。
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine("异步线程 {0},返回值 \"{1}\".", threadId, ret);
            Console.WriteLine("主线程{0}结束工作", Thread.CurrentThread.ManagedThreadId);
        }

4、通知机制

 static void Func4()
        {
            AsyncDemoModel ad = new AsyncDemoModel();
            AsyncDele dlgt = new AsyncDele(ad.TestMethod);
            //注意第三个参数,这就是我们要用到的回调方法。
            //第四个参数可以是任何Object对象,这里它就是
            //执行异步调用的委托本身,把委托本身传递进去的原因在下面可以看到。
            Console.WriteLine("异步调用完成时执行回调!!!");
            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();
        }

        //回调函数
        static void CallbackMethod(IAsyncResult ar)
        {
            //在这里,上面那个dlgt作为参数的作用得到了体现,原来它就是为了完成对EndInvoke的调用。
            AsyncDele dlgt = (AsyncDele)ar.AsyncState;
            //通过对EndInvoke的调用获取返回值。
            string ret = dlgt.EndInvoke(out threadId, ar);
            Console.WriteLine("异步线程 {0},返回值 \"{1}\".", threadId, ret);
        }
时间: 2024-10-16 15:11:21

常见异步机制分析的相关文章

Linux共享内存使用常见陷阱与分析 - 51CTO.COM http://os.51cto.com/art/201311/418977_all.htmIPC---共享内存

共享内存就是允许两个或多个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据时,不需要在客户进程和服务器进程之间幅值,因此是最快的一种IPC.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 注意:共享内存并未提供同步机制,也就是说,

Chromium的IPC消息发送、接收和分发机制分析

由于Chromium采用多进程架构,因此会涉及到进程间通信问题.通过前面一文的学习,我们知道Browser进程在启动Render进程的过程中会建立一个以UNIX Socket为基础的IPC通道.有了IPC通道之后,接下来Browser进程与Render进程就以消息的形式进行通信.我们将这种消息称为IPC消息,以区别于线程消息循环中的消息.本文就分析Chromium的IPC消息发送.接收和分发机制. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! Chrom

AndroidAdapterViewView的复用机制分析(转载)

AndroidAdapterViewView的复用机制分析 对于ListView.GridView相信大家都不陌生,重写个BaseView,实现对于的几个方法,然后就完成了我们的界面展示,并且在大部分情况下,我们加载特别多的Item也不会发生OOM,大家也都明白内部有缓存机制,都遇到过ItemView复用带来的一些问题,比如异步加载图片,最终造成界面显示的混乱,我们一般会使用setTag,然后回调显示时,避免造成混乱. 设想1:拿ListView为例,如果ListView的ItemView复用机

Linux内核态抢占机制分析(转)

Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Preemption).内核态抢占(Kernel Preemption).然后分析了在内核态下:如何判断能否抢占内核(什么是可抢占的条件):何时触发重新调度(何时设置可抢

事件拦截机制分析(Android群英传)

内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出. 当Android系统捕获到用户的各种输入事件后,如何准确地传递给真正需要这个事件的控件呢?Android给我们提供了一整套完善的事件传递.处理机制,来帮助开发者完成准确的事件分配与处理. 要了解触摸事件的拦截机制,首先要了解什么是触摸事件?顾名思义,触摸事件就是捕获触摸屏幕后产生的事件.当点击一个按钮时,通常就会产生两个或者三个事件--按钮按下,这是事件一:如果不小心滑动一点,这就是事件二:当手抬起,这是事件三.A

(转)Db2 数据库常见堵塞问题分析和处理

原文:https://www.ibm.com/developerworks/cn/analytics/library/ba-lo-db2-common-blocking-problem-analyze/index.html Db2 数据库堵塞怎么办 作为一个数据库管理员,工作中经常会遇到的一个问题:当数据库出现故障的情况下,如何快速定位问题和找到解决方案.尤其是在运维非常重要系统的时候,解决问题恢复服务是分秒必争.Db2 作为广泛使用的商业数据库,内部提供了众多方法论和诊断工具等来协助分析问题.

Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL

Linux 线程实现机制分析 Linux 线程实现机制分析  Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是

QT开发(六十三)——QT事件机制分析

QT开发(六十三)--QT事件机制分析 一.事件机制 事件是由系统或者QT平台本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应时发出,如键盘事件等:另一些事件则是由系统自动发出,如计时器事件. 事件的出现,使得程序代码不会按照原始的线性顺序执行.线性顺序的程序设计风格不适合处理复杂的用户交互,如用户交互过程中,用户点击"打开文件"将开始执行打开文件的操作,用户点击"保存文件"将开始执

Linux通信之poll机制分析

poll机制分析 韦东山 2009.12.10 所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open.sys_read.sys_write.sys_poll. 一.内核框架: 对于系统调用poll或select,它们对应的内核函数都是sys_poll.分析sys_poll,即可理解poll机制. sys_poll函数位于fs/select.c文件中,代码如下: