异步委托

来源:互联网 发布:融华财富网络贷款 编辑:程序博客网 时间:2024/05/17 23:23

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

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

1)、BeginInvoke()方法

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

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

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

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

2)、EndInvoke()方法

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

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

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

代码一,同步执行:
        delegate int MyDel(int a, int b);        static void Main(string[] args)        {            MyDel del = new MyDel(AddFun);            del.Invoke(2, 2);            while (true)         //主线程一直工作            {                Console.WriteLine("主线程{0}在工作", Thread.CurrentThread.ManagedThreadId);                Thread.Sleep(1000);            }        }        static int AddFun(int a, int b)        {            Console.WriteLine("工作线程{0}在跑着,值为{1}", Thread.CurrentThread.ManagedThreadId, a + b);            Thread.Sleep(5000);    //这里我们让线程睡眠5秒,看主线程是否被阻塞            return a + b;        }

结果:


这里停顿了5秒之后...


上面证明了这个委托会阻塞主线程...

那么如何不让它阻塞呢!想到了多线程,

但是Thread里面的委托  参数ThreadStart和ParameterThreadStart中的委托都没有返回值类型(void)

那么我们就引入主题,异步委托---


//AsyncCallBack为回调函数,委托执行完以后让回调函数去处理结果,这样就不会阻塞主线程了。

    实际也就是委托调执行以后,又一个委托把结果进行处理

        delegate int MyDel(int a, int b);        static void Main(string[] args)        {            MyDel del = new MyDel(AddFun);            //del.Invoke(2, 2);            del.BeginInvoke(1, 2, new AsyncCallback(AscCallBack), null);            while (true)            {                Console.WriteLine("主线程{0}在工作", Thread.CurrentThread.ManagedThreadId);                Thread.Sleep(1000);            }        }        static int AddFun(int a, int b)        {            Console.WriteLine("工作线程{0}在跑着,值为{1}", Thread.CurrentThread.ManagedThreadId, a + b);            Thread.Sleep(5000);            return a + b;        }        static void AscCallBack(IAsyncResult result)        {            AsyncResult aResult = (AsyncResult)result;            MyDel del = (MyDel)aResult.AsyncDelegate;            int addResult = del.EndInvoke(result);            Console.WriteLine("我是主线程还是子线程?噢原来是{0}", Thread.CurrentThread.ManagedThreadId);        }

执行结果:


到5秒的时候


我们可以看到,主线程没有被阻塞,而且工作线程和主线程不是同一个线程。

其实异步委托是在线程池内获取到一个线程,也是一种多线程的体现。

那么什么时候用多线程,什么时候用异步委托呢?  上面说过多线程的委托没有返回值,而异步委托可以自己随便定义。


当需要执行I/O操作时,使用异步操作比使用线程+同步I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.Net Remoting等跨进程的调用。
  而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。

原创粉丝点击