欢迎来到天天文库
浏览记录
ID:40534131
大小:50.50 KB
页数:4页
时间:2019-08-04
《C_多线程函数如何传参数和返回值》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、C#Delegate/委托与多线程Learning,by木公. 最近写到两个程序都用到了多线程,但是由于需要调用主线程UI,所以总是会出错,Google了一下,终于找到了使用Delegate(委托)的解决方法,现在贴出来存档并且分享: 很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程。 publicvoidThreadProc(); Threadthread=newThread(newThreadStart(ThreadProc)); thread.IsBackgroun
2、d=true; thread.Start(); 但是很多时候,在新的线程中,我们需要与UI进行交互,在.net中不允许我们直接这样做。可以参考MSDN中的描述: “Windows窗体”使用单线程单元(STA)模型,因为“Windows窗体”基于本机Win32窗口,而Win32窗口从本质上而言是单元线程。STA模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了Windows窗体之外,.NETFramework中的类使用自由线程模型。 STA模型要求需从
3、控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。基类Control为此目的提供了若干方法(Invoke、BeginInvoke和EndInvoke)。Invoke生成同步方法调用;BeginInvoke生成异步方法调用。 Windows窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个Invoke方法来将调用封送到适当的线程。 正如所看到的,我们必须调用Invoke方法,而BeginInvoke可以认为是Invoke的异步版本。调用方
4、法如下:publicdelegatevoidOutDelegate(stringtext); publicvoidOutText(stringtext) { txt.AppendText(text); txt.AppendText("tn"); } OutDelegateoutdelegate=newOutDelegate(OutText); this.BeginInvoke(outdelegate,newobject[]{text}); 如果我们需要在另外一个线程里面对UI进行操作
5、,我们需要一个类似OutText的函数,还需要一个该函数的委托delegate,当然,这里展示的是自定义的,.net中还有很多其他类型的委托,可以直接使用,不需要而外声明。例如:MethodInvoker和EventHandler,这两种类型委托的函数外观是固定的,MethodInvoker是voidFunction()类型的委托,而EventHandler是voidFunction(object,EventArgs)类型的委托,第一个不支持参数,第二中的参数类型和数量都是固定的,这两种委托可以很方便的调用,但是缺乏灵活性。请注意Be
6、ginInvoke前面的对象是this,也就是主线程。现在再介绍Control.InvokeRequired,Control是所有控件的基类,对于这个属性MSDN的描述是: 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用Invoke方法,因为调用方位于创建控件所在的线程以外的线程中。该属性可用于确定是否必须调用Invoke方法,当不知道什么线程拥有控件时这很有用。 也就是说通过判断InvokeRequired可以知道是否需要用委托来调用当前控件的一些方法,如此可以把OutText函数修改一下: publicd
7、elegatevoidOutDelegate(stringtext); publicvoidOutText(stringtext) { if(txt.InvokeRequired) { OutDelegateoutdelegate=newOutDelegate(OutText); this.BeginInvoke(outdelegate,newobject[]{text}); return; } txt.A
8、ppendText(text); txt.AppendText("tn"); } 注意,这里的函数没有返回,如果有返回,需要调用Invoke或者EndInvoke来获得返回的结果,不要因为包装而丢失
此文档下载收益归作者所有