异步委托

异步委托提供以异步方式调用同步方法的能力。

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

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

1)、BeginInvoke()方法

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

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

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

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

2)、EndInvoke()方法

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

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

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

 

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Remoting.Messaging;

namespace ConsoleApplication
{
    public delegate string DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //执行异步委托
            IAsyncResult result = delemethod.BeginInvoke("Mr.w", null, null);
            Console.WriteLine("异步调用开始:");
            string s = delemethod.EndInvoke(result);
            //主线程方法
            Console.WriteLine("异步调用结果:"+s);
            //阻止主线程退出程序
            Console.ReadKey();
        }

        //要被委托调用的方法
        static string Speaking(string name)
        {
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("我的名字是:{0}", name);
            return "委托方法执行完毕!";
        }
    }
}
复制代码

如果不调用EndInvoke,线程池中生成的线程默认的是后台线程,如果没有Console.ReadLine(),原始线程(前台线程)关闭的时候,后台线程也会关闭。

如果调用EndInvoke,没有Console.ReadLine(),异步调用没有完成,原始线程会一直阻塞,直到异步线程调用完成。

 

异步回调

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Remoting.Messaging;

namespace ConsoleApplication
{
    public delegate string DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //声明回调函数
            AsyncCallback callback = new AsyncCallback(CallBack);
            //执行异步委托

            delemethod.BeginInvoke("Mr.w", callback, null);
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            //主线程方法
            Console.WriteLine("下面我还要执行方法....");

            //阻止主线程退出程序
            Console.ReadKey();
        }
        //回调方法
        static void CallBack(IAsyncResult ar)
        {
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            AsyncResult result = (AsyncResult)ar;
            DeleMethod delemethod = (DeleMethod)result.AsyncDelegate;//通过AsyncResult的AsyncDelegate获得delemethod委托对象
            string s = delemethod.EndInvoke(ar);
            Console.WriteLine(s);
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
        }
        //要被委托调用的方法
        static string Speaking(string name)
        {

            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Console.WriteLine("我的名字是:{0}", name);
            return "委托方法执行完毕!";
        }
    }
}
复制代码

这里可以看出,如果没有Console.ReadLine(),原始线程也不会被阻塞。

http://www.cnblogs.com/IAmBetter/archive/2012/02/13/2348912.html

posted @   hongdada  阅读(297)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示