由于 Windows 窗体控件本质上不是线程安全的。因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用和死锁的情况。于是在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException
本文用一个很简单的示例来讲解这个问题(在窗体上放一个TextBox和一个Button,点击Button后,在新建的线程中设置TextBox的值)
解决办法一: 关闭该异常检测的方式来避免异常的出现
经过测试发现此种方法虽然避免了异常的抛出,但是并不能保证程序运行结果的正确性 (比如多个线程同时设置TextBox1的Text时,很难预计最终TextBox1的Text是什么)
 1 using System;
using System;
 2 using System.Collections.Generic;
using System.Collections.Generic;
 3 using System.ComponentModel;
using System.ComponentModel;
 4 using System.Data;
using System.Data;
 5 using System.Drawing;
using System.Drawing;
 6 using System.Text;
using System.Text;
 7 using System.Windows.Forms;
using System.Windows.Forms;
 8 using System.Threading;
using System.Threading;
 9
10 namespace winformTest
namespace winformTest
11

 {
{
12 public partial class Form1 : Form
    public partial class Form1 : Form
13     {
{
14 public Form1()
        public Form1()
15         {
{
16 InitializeComponent();
            InitializeComponent();
17 Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键
            Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键      
18 }
        }
19 
        
20
21 private void button1_Click(object sender, EventArgs e)
        private void button1_Click(object sender, EventArgs e)
22         {
{
23 SetTextBoxValue();
            SetTextBoxValue();
24 }
        }
25
26 void SetTextBoxValue()
        void SetTextBoxValue()
27         {
{
28 TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method1");
            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method1");
29 ThreadStart TS = new ThreadStart(tbsv.SetText);
            ThreadStart TS = new ThreadStart(tbsv.SetText);
30 Thread T = new Thread(TS);
            Thread T = new Thread(TS);
31 T.Start();
            T.Start();
32 }
        }
33
34
35 class TextBoxSetValue
        class TextBoxSetValue
36         {
{
37 private TextBox _TextBox ;
            private TextBox _TextBox ;
38 private string _Value;
            private string _Value;
39
40 public TextBoxSetValue(TextBox TxtBox, String Value)
            public TextBoxSetValue(TextBox TxtBox, String Value) 
41             {
{
42 _TextBox = TxtBox;
                _TextBox = TxtBox;
43 _Value = Value;
                _Value = Value;
44 }
            }
45
46 public void SetText()
            public void SetText() 
47             {
{
48 _TextBox.Text = _Value;
                _TextBox.Text = _Value;
49 }
            }
50 }
        }
51 }
    }
52 }
}
解决办法二:通过委托安全调用
 1 using System;
using System;
 2 using System.Collections.Generic;
using System.Collections.Generic;
 3 using System.ComponentModel;
using System.ComponentModel;
 4 using System.Data;
using System.Data;
 5 using System.Drawing;
using System.Drawing;
 6 using System.Text;
using System.Text;
 7 using System.Windows.Forms;
using System.Windows.Forms;
 8
 9 namespace winformTest
namespace winformTest
10

 {
{
11 public partial class Form2 : Form
    public partial class Form2 : Form
12     {
{
13 public Form2()
        public Form2()
14         {
{
15 InitializeComponent();
            InitializeComponent();
16 }
        }
17 
 
18
19 private void button1_Click(object sender, EventArgs e)
        private void button1_Click(object sender, EventArgs e)
20         {
{
21 SetTextBoxValue();
            SetTextBoxValue();
22 }
        }        
23
24 
       
25 private delegate void CallSetTextValue();
        private delegate void CallSetTextValue();
26 //通过委托调用
        //通过委托调用
27 void SetTextBoxValue()
        void SetTextBoxValue() 
28         {
{
29 TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method2");
            TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method2");
30 if (tbsv.TextBox.InvokeRequired)
            if (tbsv.TextBox.InvokeRequired)
31             {
{
32 CallSetTextValue call = new CallSetTextValue(tbsv.SetText);
                CallSetTextValue call = new CallSetTextValue(tbsv.SetText);
33 tbsv.TextBox.Invoke(call);
                tbsv.TextBox.Invoke(call);               
34 }
            }
35 else
            else
36             {
{
37 tbsv.SetText();
                tbsv.SetText();
38 }
            }
39 }
        }
40
41
42 class TextBoxSetValue
        class TextBoxSetValue
43         {
{
44 private TextBox _TextBox;
            private TextBox _TextBox;
45 private string _Value;
            private string _Value;
46
47 public TextBoxSetValue(TextBox TxtBox, String Value)
            public TextBoxSetValue(TextBox TxtBox, String Value)
48             {
{
49 _TextBox = TxtBox;
                _TextBox = TxtBox;
50 _Value = Value;
                _Value = Value;
51 }
            }
52
53 public void SetText()
            public void SetText()
54             {
{
55 _TextBox.Text = _Value;
                _TextBox.Text = _Value;
56 }
            }
57
58
59            public TextBox TextBox  {
{
60                set  { _TextBox = value; }
{ _TextBox = value; }
61                get  { return _TextBox; }
{ return _TextBox; }
62 }
            }           
63 }
        }
64 }
    }
65 }
}
 
		 随时随地看视频
随时随地看视频 
				 
				 
				 
				 
				