书是书,你是你,照抄文字那是书本的东西,你必须有你自己理解,就算是 有错误的认识。下面说下异步委托,个人涉 .net不深,经验尚浅,如果说的不对,希望大家指出来。
对于线程,我不想多说了,可以搜索博客园 风尘浪子的 "线程上与线程下",说的相当详细。本篇博文就是针对:了解一些线程但对异步委托又模糊的朋友。
其实这个异步委托,应该结合 线程Thread来一起讨论的,为什么我们现在对这个异步委托爱不释手,是因为它的3个原因:
.不影响主线程的执行
.合理的利用ThreadPool线程池的线程
.异步委托本质是调用了线程池的工作者线程,不需要为了新建和注销线程烦恼,统一由线程池管理。
1.传统的同步委托(模拟委托的方法执行时间很长)
模拟委托的方法执行很长: Thread.Sleep(TimeSpan.FromSeconds(3));
View Code
//声明委托
public delegate void DeleMethod(string name);
class Program
{
static void Main(string[] args)
{
DeleMethod delemethod = Speaking;
delemethod("Mr.w");
Console.WriteLine("下面我还要执行方法....");
}
//要被委托调用的方法
static void Speaking(string name)
{
Console.WriteLine("我的名字是:{0}",name);
//利用休眠3秒钟,模拟委托执行的方法很长
Thread.Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("委托方法执行完毕!");
}
分析:
.按F11大家都可以自己分析了,Main()是所有程序的开始,该程序调用Speaking()方法会休眠3秒,这样影响了主线程的下面的方法执行时间。
.从头到尾,程序都只有一个线程,思考下:可不可以在利用一个子线程去帮我执行我的委托方法,不影响我的主线。
答案是:可以,对于这种情况,我们可以 新建Thread类的线程,或者利用异步委托(线程池的工作者线程),这里我们不适用新建的线程,因为它不便于管理。
2.初始异步委托
View Code
//声明委托
public delegate void DeleMethod(string name);
class Program
{
static void Main(string[] args)
{
DeleMethod delemethod = Speaking;
//执行异步委托
delemethod.BeginInvoke("Mr.w",null,null);
//主线程方法
Console.WriteLine("下面我还要执行方法....");
}
//要被委托调用的方法
static void Speaking(string name)
{
Console.WriteLine("我的名字是:{0}",name);
//利用休眠3秒钟,模拟委托执行的方法很长
Thread.Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("委托方法执行完毕!");
}
}
输出:
下面我还要执行方法....
我的名字是:Mr.w
复制代码
分析:
1.怎么回事?怎么好像 委托方法没有执行完毕?
答:线程分为:前台线程和后台线程,默认线程池的都是后台线程,主线程是不会管 后台线程是否执行完毕,就直接退出程序。新建的Thread类的线程默认是前台线程,主线程必须等待他执行完毕再退出AppDomain.
是否是前台或者后台线程取决于:IsBackground属性。
2.我们利用一个Console.ReadKey();可以让主线程不退出AppDomain。
3.说一说带返回值的异步委托
大家都知道,有时候,主线程根本就不关心 委托方法的返回值,所以是否能把 异步委托的返回值 显示在我的主窗口就更不关心了,但是返回值 也是可以解决很多问题的:
1.上篇博文已经提及了,非void委托方法可以返回 异常信息
2.有些软件需要 把委托方法的返回值 作为另一个方法的参数来处理
代码1:
View Code
//声明委托
public delegate string DeleMethod(string name);
class Program
{
static void Main(string[] args)
{
DeleMethod delemethod = Speaking;
//执行异步委托
IAsyncResult result=delemethod.BeginInvoke("Mr.w",null,null);
string s=delemethod.EndInvoke(result);
//主线程方法
Console.WriteLine("下面我还要执行方法....");
//阻止主线程退出程序
Console.ReadKey();
}
//要被委托调用的方法
static string Speaking(string name)
{
//利用休眠3秒钟,模拟委托执行的方法很长
Thread.Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("我的名字是:{0}", name);
return "委托方法执行完毕!";
}
}
输出:
我的名字是:Mr.w
下面我还要执行方法....
复制代码
注意:
看输出的结果,按照我们的理论,应该输出结果是:
下面我还要执行方法....
我的名字是:Mr.w
复制代码
怎么结果相反了?
答案:
1.因为异步委托 由 BeginInvoke()方法开始,以EndInvoke()结束。
2.异步委托的返回值是由 EndInvoke();返回的。
所以:你如果想要返回值,必须写EndInvoke();,可是有人要问了,如果在主线程调用EndInvoke()方法,主线程不是要等待 子线程执行完毕之后才 会执行下面的代码,这和 同步执行有什么区别?那异步就没有意义了。
正确!完全正确,但是有没有 又可以得到异步委托的结果,又不影响主线程的方式。
4.说一说 得到返回值,又不影响主线程的方式
解决这个问题,必须了解下,异步委托的BeginInvoke()方法
1.BeginInvoke()最容易被忘记的是:执行BeginInvoke()方法的委托变量,如上面的:delemethod变量必须是单播委托,也就是说只能绑定一个方法。对于多播委托,请把所有方法遍历出来在使用异步委托,如何遍历查询我的上一篇博文。
2.BeginInvoke()方法有4个参数,前2个是和你的委托方法的参数一致的,后2个参数,分别是AsyncCallback类型和Object类型,其中AsyncCallback是一个委托类型,它用于当异步执行完毕时自动进行调用的方法,最后一个参数Object类型可以通过 AsyncResult类型变量的AsyncState属性获得,或者 IAsyncResult类型变量的AsyncState属性
3.BeginInvoke()方法 返回值是 一个IAsyncResult接口,实质就是AsyncResult的对象。通过AsyncResult的AsyncDelegate获得delemthod委托对象,然后再在其上调用EndInvoke()方法。
是不是越来越迷糊,结合案例看:
代码1:
View Code
//声明委托
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,delemethod);
//主线程方法
Console.WriteLine("下面我还要执行方法....");
//阻止主线程退出程序
Console.ReadKey();
}
//回调方法
static void CallBack(IAsyncResult ar)
{
DeleMethod delemethod = (DeleMethod)ar.AsyncState;//BeginInvoke()方法返回的对象的属性AsyncState,就是BeginInvoke()方法最后一个Object参数
string s = delemethod.EndInvoke(ar);
Console.WriteLine(s);
}
//要被委托调用的方法
static string Speaking(string name)
{
//利用休眠3秒钟,模拟委托执行的方法很长
Thread.Sleep(TimeSpan.FromSeconds(3));
Console.WriteLine("我的名字是:{0}", name);
return "委托方法执行完毕!";
}
}
输出:
下面我还要执行方法....
我的名字是:Mr.w
委托方法执行完毕!
复制代码
先看结果:结果是符合我们的理论的。
分析:
1.大家都知道异步委托要想有返回值,必须调用EndInvoke()方法,但是用哪个委托变量调用呢?
.BeginInvoke()方法最后一个参数就是 BeginInvoke()返回值的IAsyncResult类型变量的AsyncState,这样获取委托变量的对象,如代码1
.或者通过AsyncResult的AsyncDelegate获得delemethod委托对象,然后再在其上调用EndInvoke()方法。如代码2
代码2:
View Code
//声明委托
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 "委托方法执行完毕!";
}
}
输出:
当前线程ID:1
下面我还要执行方法....
当前线程ID:3
我的名字是:Mr.w
当前线程ID:3
委托方法执行完毕!
当前线程ID:3
分享到:
相关推荐
00--简单的异步委托 01--带回调函数 02--带返回值的异步委托 03--带返回值的泛型异步委托
为了给用户提供更好的体验,读取数据库等程序需要长时间来执行的操作,需要弹出一个等待界面。可以一边执行需要等待的操作,一边...本资源使用VS2017软件,VB.NET编程,异步委托和多线程编程实现背景透明的等待窗体。
简单定时器使用及delegate的begininvoke,测试其异步调用是否真的开辟了线程,同时提供异步委托执行完成后的函数处理
c#委托事件异步例子,委托,异步委托,事件
控件句柄异步委托.rar相关资料,真的很详细
异步委托调用的简单例子,一看就明白,你懂得
今天小编就为大家分享一篇关于C#用委托BeginInvoke做异步线程,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
天轰穿老师VS2010趣味编程视频教程,第43讲,线程通信与异步委托,FLV格式,压缩包自带10%恢复记录
一个很不错的socket 异步传输的文件的实例,包括服务器端和客户端,供大家下载学习
老实讲,哥只想做台设备,真没想整的这么高深,是客户逼我的,不想说太多,自己看代码,同步委托里面也有,被屏蔽了。 实用至上!
使用异步委托如何取回返回值的标准做法 该示例演示了在线程和主线程ui界面间操作的方法精髓。
学习socket 多线程 异步 不可或缺 不可多得的项目实例!我看了之后收获颇多,在此分享 希望更多人可以获得新知识!
该代码用oc实现了异步下载网上图片的瀑布流照片墙,使用图片缓存机制
TCP网络编程的学习过程源码(委托、线程、同步、异步)等
使用.Net 的委托机制来为我们的程序提供异步操作行为. 1步, 为我们的AsyncTest(Hello方法) 声明一个委托 public delegate string AsyncEventHandler(string name); 2步,使用委托提供的BeginInvoke, EndInvoke 方法...
kissy 开源瀑布流,完整异步加载模拟效果(php后端)
C#,委托,异步,调用.窗体,通讯,介绍窗体间通讯的一种较好方法
异步委托的小示例,仅供初学者参考,大神请绕道。
//委托异步 Action<string> showMessage = ShowMessage; IAsyncResult result = showMessage.BeginInvoke(测试异步委托,null, null); //那在异步线程未完成工作以前主线程将处于阻塞状态 //等到异步线程结束,...
利用C#语言实现Socket异步通信,并利用事件与委托实现消息的传递,同时通信功能与界面处理功能分离处理。利于学习异步通信、委托和事件。