欢迎来到天天文库
浏览记录
ID:15708269
大小:25.40 KB
页数:4页
时间:2018-08-05
《三种方法来解决跨线程访问控件的问题》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、访问Windows窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。.NETFramework有助于在以非线程安全方式访问控件时检测到这一问题。在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个InvalidOperationException,并提示消息:“从不是创建控件controlname的线程访问它。”此异常在调试期间和运行时的某些情况下可靠地发生。强烈建议您在显示
2、此错误信息时修复此问题。在调试以.NETFramework2.0版之前的.NETFramework编写的应用程序时,可能会出现此异常。注意 可以通过将CheckForIllegalCrossThreadCalls属性的值设置为false来禁用此异常。这会使控件以与在VisualStudio2003下相同的方式运行。下面的代码示例演示如何从辅助线程以线程安全方式和非线程安全方式调用Windows窗体控件。它演示一种以非线程安全方式设置 TextBox 控件的 Text 属性的方法,还演示两种以线程安全方式设置Text属性的方法。usingSystem;usingSy
3、stem.ComponentModel;usingSystem.Threading;usingSystem.Windows.Forms;namespaceCrossThreadDemo{publicclassForm1:Form{//代理实现异步调用以设置TextBox控件text属性delegatevoidSetTextCallback(stringtext);//此线程用来演示线程安全和非安全两种方式来调用一个windows窗体控件privateThreaddemoThread=null;//此后台工作者(BackgroundWorker)用来演示执行异步操作
4、的首选方式privateBackgroundWorkerbackgroundWorker1;privateTextBoxtextBox1;privateButtonsetTextUnsafeBtn;privateButtonsetTextSafeBtn;privateButtonsetTextBackgroundWorkerBtn;privateSystem.ComponentModel.IContainercomponents=null;publicForm1(){InitializeComponent();}protectedoverridevoidDispo
5、se(booldisposing){if(disposing&&(components!=null)){components.Dispose();}base.Dispose(disposing);}//此事件句柄创建一个ie线程以非安全方式调用一个windows窗体控件privatevoidsetTextUnsafeBtn_Click(objectsender,EventArgse){this.demoThread=newThread(newThreadStart(this.ThreadProcUnsafe));this.demoThread.Start();}/
6、/此方法在工作者线程执行并且对TextBox控件作非安全调用privatevoidThreadProcUnsafe(){this.textBox1.Text="Thistextwassetunsafely.";}//此事件句柄创建一个以线程安全方式调用windows窗体控件的线程privatevoidsetTextSafeBtn_Click(objectsender,EventArgse){this.demoThread=newThread(newThreadStart(this.ThreadProcSafe));this.demoThread.Start();}
7、//此方法在工作者线程执行并且对TextBox控件作线程安全调用privatevoidThreadProcSafe(){this.SetText("Thistextwassetsafely.");}//此方法演示一个对windows窗体控件作线程安全调用的模式////如果调用线程和创建TextBox控件的线程不同,这个方法创建//代理SetTextCallback并且自己通过Invoke方法异步调用它//如果相同则直接设置Text属性privatevoidSetText(stringtext){//InvokeRequired需要比较调用线程ID和创建线程ID//
8、如果它们不
此文档下载收益归作者所有