C子线程调用其它窗体

上传人:平*** 文档编号:11055795 上传时间:2017-10-11 格式:DOC 页数:7 大小:33.43KB
返回 下载 相关 举报
C子线程调用其它窗体_第1页
第1页 / 共7页
C子线程调用其它窗体_第2页
第2页 / 共7页
C子线程调用其它窗体_第3页
第3页 / 共7页
C子线程调用其它窗体_第4页
第4页 / 共7页
C子线程调用其它窗体_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《C子线程调用其它窗体》由会员分享,可在线阅读,更多相关《C子线程调用其它窗体(7页珍藏版)》请在金锄头文库上搜索。

1、C#中窗体之间的相互调用第 1 页 共 7 页C# 子线程调用其它窗体有很多朋友不知道怎么在 thread 中打开一个窗体,总是说没有反应,下面我就说说这方面自己的经验。代码如下:private void ThreadFunc()/run your coding;Form temp = new Form();temp.Show();/run your coding;private void button1_Click(object sender, System.EventArgs e)FormThread = new Thread( new ThreadStart( ThreadFunc )

2、);FormThread.Start();像上面的代码,若点击 button 按钮,大家可以看到被创建的窗体闪了一下,就消失了,这是因为你在线程中建的窗体,所有的资源都是属于这个线程的,所以当这个线程结束后,它的资源也被回收了,当然 C#也就自动把窗体给关闭了。正确的方法是用 Invoke 调用,代码如下:private void ThreadFunc()MethodInvoker mi = new MethodInvoker(this.ShowForm);this.BeginInvoke(mi);private void ShowForm( )Form temp = new Form();t

3、emp.Show();private void button1_Click(object sender, System.EventArgs e)FormThread = new Thread( new ThreadStart( ThreadFunc ) );FormThread.Start();C#中窗体之间的相互调用第 2 页 共 7 页C#多线程调用 Winform 窗体每一个从 Control 类中派生出来的 WinForm 类(包括 Control 类)都是依靠底层 Windows 消息和一个消息泵循环(message pump loop)来执行的。消息循环都必须有一个相对应的线程,因

4、为发送到一个 window的消息实际上只会被发送到创建该 window 的线程中去。其结果是,即使提供了同步(synchronization ) ,你也无法从多线程中调用这些处理消息的方法。大多数 plumbing 是掩藏起来的,因为 WinForm 是用代理(delegate)将消息绑定到事件处理方法中的。WinForm 将 Windows 消息转换为一个基于代理的事件,但你还是必须注意,由于最初消息循环的缘故,只有创建该 form 的线程才能调用其事件处理方法。如果你在你自己的线程中调用这些方法,则它们会在该线程中处理事件,而不是在指定的线程中进行处理。你可以从任何线程中调用任何不属于消息

5、处理的方法。Control 类(及其派生类)实现了一个定义在 System.ComponentModel 命名空间下的接口 - ISynchronizeInvoke,并以此来处理多线程中调用消息处理方法的问题: public interface ISynchronizeInvoke object Invoke(Delegatemethod,object args); IAsyncResult BeginInvoke(Delegatemethod,object args); object EndInvoke(IAsyncResult result); bool InvokeRequired ge

6、t; ISynchronizeInvoke 提供了一个普通的标准机制用于在其他线程的对象中进行方法调用。例如,如果一个对象实现了 ISynchronizeInvoke,那么在线程 T1 上的客户端可以在该对象中调用 ISynchronizeInvoke 的 Invoke()方法。Invoke()方法的实现会阻塞(block)该线程的调用,它将调用打包发送(marshal)到 T2,并在 T2 中执行调用,再将返回值发送会 T1,然后返回到 T1 的客户端。Invoke()方法以一个代理来定位该方法在 T2 中的调用,并以一个普通的对象数组做为其参数。 调用者还可以检查 InvokeRequir

7、ed 属性,因为你既可以在同一线程中调用 ISynchronizeInvoke 也可以将它重新定位(redirect)到其他线程中去。如果 InvokeRequired 的返回值是 false 的话,则调用者可以直接调用该对象的方法。 比如,假设你想要从另一个线程中调用某个 form 中的 Close 方法,那么你可以使用预先定义好的的MethodInvoker 代理,并调用 Invoke 方法: Form form; /* obtain a reference to the form, then: */ ISynchronizeInvoke synchronizer; synchronize

8、r = form; C#中窗体之间的相互调用第 3 页 共 7 页if(synchronizer.InvokeRequired) MethodInvoker invoker = new MethodInvoker(form.Close); synchronizer.Invoke(invoker,null); else form.Close(); ISynchronizeInvoke 不仅仅用于 WinForm 中。例如,一个 Calculator 类提供了将两个数字相加的 Add()方法,它就是通过 ISynchronizeInvoke 来实现的。用户必须确定 ISynchronizeInvo

9、ke.Invoke()方法的调用是执行在正确的线程中的。 列表 A. Calculator 类的 Add()方法用于将两个数字相加。如果用户直接调用 Add()方法,它会在该用户的线程中执行调用,而用户可以通过 ISynchronizeInvoke.Invoke()将调用写入正确的线程中。列表 A: public class Calculator : ISynchronizeInvoke public int Add(int arg1,int arg2) int threadID = Thread.CurrentThread.GetHashCode(); Trace.WriteLine( Ca

10、lculator thread ID is + threadID.ToString(); return arg1 + arg2; /ISynchronizeInvoke implementation public object Invoke(Delegate method,object args) public IAsyncResult BeginInvoke(Delegate method,object args) public object EndInvoke(IAsyncResult result) public bool InvokeRequired /Client-side code

11、 public delegate int AddDelegate(int arg1,int arg2); int threadID = Thread.CurrentThread.GetHashCode(); Trace.WriteLine(Client thread ID is + threadID.ToString(); Calculator calc; /* Some code to initialize calc */ C#中窗体之间的相互调用第 4 页 共 7 页AddDelegate addDelegate = new AddDelegate(calc.Add); object ar

12、r = new object2; arr0 = 3; arr1 = 4; int sum = 0; sum = (int) calc.Invoke(addDelegate,arr); Debug.Assert(sum =7); /* Possible output: Calculator thread ID is 29 Client thread ID is 30 */ 或许你并不想进行同步调用,因为它被打包发送到另一个线程中去了。你可以通过 BeginInvoke()和EndInvoke()方法来实现它。你可以依照通用的.NET 非同步编程模式(asynchronous programmin

13、g model)来使用这些方法:用 BeginInvoke()来发送调用,用 EndInvoke()来实现等待或用于在完成时进行提示以及收集返回结果。 还值得一提的是 ISynchronizeInvoke 方法并非安全类型。 类型不符会导致在执行时被抛出异常,而不是编译错误。所以在使用 ISynchronizeInvoke 时要格外注意,因为编辑器无法检查出执行错误。 实现 ISynchronizeInvoke 要求你使用一个代理来在后期绑定(late binding)中动态地调用方法。每一种代理类型均提供 DynamicInvoke()方法: public object DynamicInv

14、oke(object args); 理论上来说,你必须将一个方法代理放到一个需要提供对象运行的真实的线程中去,并使 Invoke() 和BeginInvoke()方法中的代理中调用 DynamicInvoke()方法。 ISynchronizeInvoke 的实现是一个非同一般的编程技巧,本文附带的源文件中包含了一个名为 Synchronizer 的帮助类(helper class)和一个测试程序,这个测试程序是用来论证列表 A 中的 Calculator 类是如何用 Synchronizer 类来实现 ISynchronizeInvoke 的。Synchronizer 是 ISynchron

15、izeInvoke 的一个普通实现,你可以使用它的派生类或者将其本身作为一个对象来使用,并将 ISynchronizeInvoke 实现指派给它。 用来实现 Synchronizer 的一个重要元素是使用一个名为 WorkerThread 的嵌套类(nested class) 。WorkerThread 中有一个工作项目(work item)查询。WorkItem 类中包含方法代理和参数。Invoke()和BeginInvoke()用来将一个工作项目实例加入到查询里。WorkerThread 新建一个.NET worker 线程,它负责监测工作项目的查询任务。查询到项目之后,worker 会读

16、取它们,然后调用 DynamicInvoke()方法。C#中窗体之间的相互调用第 5 页 共 7 页C# API 调用怎么获得窗体内容?DllImport ( user32.dll, EntryPoint = FindWindow, SetLastError = true ) private static extern IntPtr FindWindow( string lpClassName, string lpWindowName ); DllImport ( user32.dll, EntryPoint = FindWindowEx, SetLastError = true ) private static extern IntPtr FindWindowEx( IntPtr hwndParent, uint hwndChildAfter,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号