sharplife


software is a artwork, also make the life better !!!
  首页  :: 联系 :: 订阅 订阅  :: 管理

总结.NET中异步通讯[读win control]

Posted on 2007-02-08 09:17  sharplife  阅读(855)  评论(1编辑  收藏  举报

.NET中实现异步操作的三种方式:

异步委托、用BackgroundWorker组件、显式使用System.Threading.Thread

上述三种技术中核心都是使用线程,各有其适合的使用场所,其中前两种较为方便,适合完成单任务的异步操作,但第三种扩展性、灵活性最高,下面会各个介绍。

Tip:Sytsem.Windows.Forms.Timer组件并不提供多线程操作的功能,其是利用应用程序的idle moment触发其Tick事件完成相应的操作,操作的执行完全同一主线程中执行,这样UI更新、同步不是问题,但同时当你在Tick事件处理中完成time-consuming性操作时将会是问题(如非用户界面友好性等)。

.NET中提供了几种Timer,其中有于其他线程完成操作的(即多线程),可参见:http:
//msdn.microsoft.com/msdnmag/issues/04/02/TimersinNET

  

异步委托的使用方式:
public delegate int doSomeDele(int para);//定义委托
doSomeDele dsd = new doSomeDele(obj.method);//实例化委托
//开始异步调用并注册callback函数,于异步线程中执行obj.method
dsd.BeginInvoke(para,new AsyncCallBck(myCallBack),dsd);

private void myCallBack(IasyncResult async)//于异步线程中执行
{
//取回传入的原委托实例
doSomeDele dosome = (doSomeDele)async.AsyncState;
//取委托调用的所得的结果
int ret = dosome.EndInvoke(async);
}


原理:异步委托的实现不会创建新的线程,其所用的线程将由clr所管理的线程池(单cpu计算机最多25线程)维护,超过线程池容量的线程需求将等待

异步委托的调用在涉及更新winAppui(也即主线程外的线程更新ui),将由controlInvokeReqired属性(如果当前code不是runningcontrol被创建的线程其值为true)和Invoke方法(在ui的线程上触发方法)完成。

//允许任意签名的委托
control.Invoke(new customDelegate(…),new object[]{…});
//.net提供无参的委托
control.Invoke(new MethodInvoker(…))

原理:control.Invoke的执行将首先检查其windows handle是否存在,若存在,Invoke方法将用win32 api 的GetWindowThreadProcessId()为control获取thread id,并与当前执行线程的id –GetCurrentThreadId()
-比较以决定是否需要marshalling(不等,则需要此操作)。若其windows handle不存在,Invoke将向上回溯在其parent(or parent’parent etc)的寻找,因此一个动态创建的control,其上激发的Invoke将比期望的执行略慢,当然你可以直接调用其父控件的Invoke,或在调用前检查control.Handle是否存在。Marshal 用户method将由Invoke用win api PostMessage在消息队列在为ui thread post一个消息,直到主线程的idle moment将处理此消息(建议将主线程中rocessor-intensive任务在其他线程中完成)

关于control.Invoke的更多:http:
//weblogs.asp.net/justin_rogers/articles/126345.aspx


BackgroundWorker
组件的使用:

backgroundWorker.RunWorkerAsync(customObject);
//当backgroundWorker获得线程后将触发DoWork事件,所以可以注册其事件处理
//其中DoWorkEventArgs的Argument可获取传入的customObject,Result属性用
//于保存获取的结果,此中执行任务
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
//上述方法执行完毕backgroundWorker将触发RunWorkerCompleted事件
//可于此进行UI相关操作,其中RunWorkerCompletedEventArgs的Result
//属性用于获取上述方法中的结果
void backgroundWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)

另外BackgroundWorker还可提供report process功能,但除非自定义接口进行包装,否则将把线程任务和ui紧密耦合,当然亦可使用Thread取完成此功能。

 

System.Threading.Thread自不必多说(可说的太多了),完成.net的多线程编程,详细的多线程编程可参见具体书籍,如c# thread handbook等,等以后用的多了再总结。