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


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

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

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

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

     1using System;
     2using System.Collections.Generic;
     3using System.ComponentModel;
     4using System.Data;
     5using System.Drawing;
     6using System.Text;
     7using System.Windows.Forms;
     8using System.Threading;
     9
    10namespace winformTest
    11{
    12    public partial class Form1 : Form
    13    {
    14        public Form1()
    15        {
    16            InitializeComponent();
    17            Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键      
    18        }

    19        
    20
    21        private void button1_Click(object sender, EventArgs e)
    22        {
    23            SetTextBoxValue();
    24        }

    25
    26        void SetTextBoxValue()
    27        {
    28            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method1");
    29            ThreadStart TS = new ThreadStart(tbsv.SetText);
    30            Thread T = new Thread(TS);
    31            T.Start();
    32        }

    33
    34
    35        class TextBoxSetValue
    36        {
    37            private TextBox _TextBox ;
    38            private string _Value;
    39
    40            public TextBoxSetValue(TextBox TxtBox, String Value) 
    41            {
    42                _TextBox = TxtBox;
    43                _Value = Value;
    44            }

    45
    46            public void SetText() 
    47            {
    48                _TextBox.Text = _Value;
    49            }

    50        }

    51    }

    52}

    解决办法二:通过委托安全调用
     1using System;
     2using System.Collections.Generic;
     3using System.ComponentModel;
     4using System.Data;
     5using System.Drawing;
     6using System.Text;
     7using System.Windows.Forms;
     8
     9namespace winformTest
    10{
    11    public partial class Form2 : Form
    12    {
    13        public Form2()
    14        {
    15            InitializeComponent();
    16        }

    17 
    18
    19        private void button1_Click(object sender, EventArgs e)
    20        {
    21            SetTextBoxValue();
    22        }
            
    23
    24       
    25        private delegate void CallSetTextValue();
    26        //通过委托调用
    27        void SetTextBoxValue() 
    28        {
    29            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method2");
    30            if (tbsv.TextBox.InvokeRequired)
    31            {
    32                CallSetTextValue call = new CallSetTextValue(tbsv.SetText);
    33                tbsv.TextBox.Invoke(call);               
    34            }

    35            else
    36            {
    37                tbsv.SetText();
    38            }

    39        }

    40
    41
    42        class TextBoxSetValue
    43        {
    44            private TextBox _TextBox;
    45            private string _Value;
    46
    47            public TextBoxSetValue(TextBox TxtBox, String Value)
    48            {
    49                _TextBox = TxtBox;
    50                _Value = Value;
    51            }

    52
    53            public void SetText()
    54            {
    55                _TextBox.Text = _Value;
    56            }

    57
    58
    59            public TextBox TextBox {
    60                set { _TextBox = value; }
    61                get return _TextBox; }
    62            }
               
    63        }

    64    }

    65}
    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    2、selinux服务的操作
    1、添加nginx到全局变量中
    linux每日命令(1):which
    QT重载基类绘制函数并在基类绘制结果基础上进行子类的绘制
    QT信号槽无法正常通信的原因
    mapgis6.7+加密狗+二次开发SDK库
    KMP算法参考及C语言实现
    elastic search
    RabbitMq docker集群
    RabbitMq安装
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1007596.html
Copyright © 2020-2023  润新知