前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在多线程中调用winform窗体控件

如何在多线程中调用winform窗体控件

作者头像
菩提树下的杨过
发布2018-01-22 16:44:10
2.2K0
发布2018-01-22 16:44:10
举报

由于 Windows 窗体控件本质上不是线程安全的。因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用和死锁的情况。于是在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException 

本文用一个很简单的示例来讲解这个问题(在窗体上放一个TextBox和一个Button,点击Button后,在新建的线程中设置TextBox的值)

解决办法一: 关闭该异常检测的方式来避免异常的出现

经过测试发现此种方法虽然避免了异常的抛出,但是并不能保证程序运行结果的正确性 (比如多个线程同时设置TextBox1的Text时,很难预计最终TextBox1的Text是什么)

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace winformTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键      
        }
        

        private void button1_Click(object sender, EventArgs e)
        {
            SetTextBoxValue();
        }

        void SetTextBoxValue()
        {
            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method1");
            ThreadStart TS = new ThreadStart(tbsv.SetText);
            Thread T = new Thread(TS);
            T.Start();
        }


        class TextBoxSetValue
        {
            private TextBox _TextBox ;
            private string _Value;

            public TextBoxSetValue(TextBox TxtBox, String Value) 
            {
                _TextBox = TxtBox;
                _Value = Value;
            }

            public void SetText() 
            {
                _TextBox.Text = _Value;
            }
        }
    }
}

解决办法二:通过委托安全调用

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace winformTest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
 

        private void button1_Click(object sender, EventArgs e)
        {
            SetTextBoxValue();
        }        

       
        private delegate void CallSetTextValue();
        //通过委托调用
        void SetTextBoxValue() 
        {
            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method2");
            if (tbsv.TextBox.InvokeRequired)
            {
                CallSetTextValue call = new CallSetTextValue(tbsv.SetText);
                tbsv.TextBox.Invoke(call);               
            }
            else
            {
                tbsv.SetText();
            }
        }


        class TextBoxSetValue
        {
            private TextBox _TextBox;
            private string _Value;

            public TextBoxSetValue(TextBox TxtBox, String Value)
            {
                _TextBox = TxtBox;
                _Value = Value;
            }

            public void SetText()
            {
                _TextBox.Text = _Value;
            }


            public TextBox TextBox {
                set { _TextBox = value; }
                get { return _TextBox; }
            }           
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2007-12-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档