分享
分享赚钱 收藏 举报 版权申诉 / 4

类型Delegate委托与多线程(线程调用主窗口控件).doc

  • 上传人:hwpkd79526
  • 文档编号:7227012
  • 上传时间:2019-05-10
  • 格式:DOC
  • 页数:4
  • 大小:38.50KB
  • 配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    Delegate委托与多线程(线程调用主窗口控件).doc
    资源描述:

    1、最近写到两个程序都用到了多线程,但是由于需要调用主线程 UI,所以总是会出错,Google 了一下,终于找到了使用 Delegate(委托)的解决方法,现在贴出来存档并且分享: 很多时候写 windows程序都需要结合多线程,在.net 中用如下得代码来创建并启动一个新的线程。public void ThreadProc();Thread thread = new Thread(new ThreadStart(ThreadProc);thread.IsBackground = true;thread.Start();但是很多时候,在新的线程中,我们需要与 UI进行交互,在.net 中不允许我们

    2、直接这样做。可以参考 MSDN中的描述:“Windows 窗体”使用单线程单元 (STA) 模型,因为“Windows 窗体”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。STA 模型要求需从控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。基类 Control 为此目的提供了若干方法(Invoke、BeginInvoke 和 E

    3、ndInvoke)。Invoke 生成同步方法调用;BeginInvoke 生成异步方法调用。Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。正如所看到的,我们必须调用 Invoke方法,而 BeginInvoke可以认为是Invoke的异步版本。调用方法如下:public delegate void OutDelegate(string text);public void OutText(string text)txt.AppendText(text);txt.Appe

    4、ndText( “tn“ );OutDelegate outdelegate = new OutDelegate( OutText );this.BeginInvoke(outdelegate, new objecttext);如果我们需要在另外一个线程里面对 UI进行操作,我们需要一个类似 OutText的函数,还需要一个该函数的委托 delegate,当然,这里展示的是自定义的,.net中还有很多其他类型的委托,可以直接使用,不需要而外声明。例如:MethodInvoker和 EventHandler,这两种类型委托的函数外观是固定的,MethodInvoker是 void Functio

    5、n()类型的委托,而 EventHandler是 void Function(object, EventArgs)类型的委托,第一个不支持参数,第二中的参数类型和数量都是固定的,这两种委托可以很方便的调用,但是缺乏灵活性。请注意 BeginInvoke前面的对象是 this,也就是主线程。现在再介绍Control.InvokeRequired,Control 是所有控件的基类,对于这个属性 MSDN的描述是:获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。该属性可用于确定是否必须调用 Invoke 方法,当不知道什

    6、么线程拥有控件时这很有用。也就是说通过判断 InvokeRequired可以知道是否需要用委托来调用当前控件的一些方法,如此可以把 OutText函数修改一下:public delegate void OutDelegate(string text);public void OutText(string text)if( txt.InvokeRequired )OutDelegate outdelegate = new OutDelegate( OutText );this.BeginInvoke(outdelegate, new objecttext);return;txt.AppendTe

    7、xt(text);txt.AppendText( “tn“ );注意,这里的函数没有返回,如果有返回,需要调用 Invoke或者 EndInvoke来获得返回的结果,不要因为包装而丢失了返回值。如果调用没有完成,Invoke和 EndInvoke都将会引起阻塞。现在如果我有一个线程函数如下:public void ThreadProc()for(int i = 0; i 5; i+)OutText( i.ToString() );Thread.Sleep(1000);如果循环的次数很大,或者漏了 Thread.Sleep(1000);,那么你的 UI肯定会停止响应,想知道原因吗?看看 Begi

    8、nInvoke前面的对象,没错,就是 this,也就是主线程,当你的主线程不停的调用 OutText的时候,UI 当然会停止响应。与以前 VC中创建一个新的线程需要调用 AfxBeginThread函数,该函数中第一个参数就是线程函数的地址,而第二个参数是一个类型为 LPVOID的指针类型,这个参数将传递给线程函数。现在我们没有办法再使用这种方法来传递参数了。我们需要将传递给线程的参数和线程函数包装成一个单独的类,然后在这个类的构造函数中初始化该线程所需的参数,然后再将该实例的线程函数传递给 Thread类的构造函数。代码大致如下:public class ProcClassprivate s

    9、tring procParameter = “;public ProcClass(string parameter)procParameter = parameter;public void ThreadProc()ProcClass threadProc = new ProcClass(“use thread class“);Thread thread = new Thread( new ThreadStart( threadProc.ThreadProc ) );thread.IsBackground = true;thread.Start();就是这样,需要建立一个中间类来传递线程所需的

    10、参数。那么如果我的线程又需要参数,又需要和 UI进行交互的时候该怎么办呢?可以修改一下代码:public class ProcClassprivate string procParameter = “;private Form1.OutDelegate delg = null;public ProcClass(string parameter, Form1.OutDelegate delg)procParameter = parameter;this.delg = delg;public void ThreadProc()delg.BeginInvoke(“use ProcClass.Thre

    11、adProc()“, null, null);ProcClass threadProc = new ProcClass(“use thread class“, new OutDelegate(OutText);Thread thread = new Thread( new ThreadStart( threadProc.ThreadProc ) );thread.IsBackground = true;thread.Start();/以下为自己写的异步委托的例子 namespace PhsControlDelegatepublic partial class Form2 : FormPhsCo

    12、ntrol.phsControl phsObj = new PhsControl.phsControl();public delegate void OperationDelegate(string strMessage);public Form2()phsObj.OnJieShouDuanXin +=new PhsControl.JieShouDXHandler(phsObj_OnJieShouDuanXin);public void SetText(string strMessage)txtReceive.AppendText(strMessage);protected void phsObj_OnJieShouDuanXin(Object sender, PhsControl.jsSmsArgs e)OperationDelegate optionDelgate = new OperationDelegate(SetText);this.BeginInvoke(optionDelgate, new object e.dhHaoMa + “ “ + e.dxNeiRong + “tn“ );

    展开阅读全文
    提示  道客多多所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:Delegate委托与多线程(线程调用主窗口控件).doc
    链接地址:https://www.docduoduo.com/p-7227012.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    道客多多用户QQ群:832276834  微博官方号:道客多多官方   知乎号:道客多多

    Copyright© 2025 道客多多 docduoduo.com 网站版权所有世界地图

    经营许可证编号:粤ICP备2021046453号    营业执照商标

    1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10.png



    收起
    展开