由於 Windows 窗體控件本質上不是線程安全的。因此如果有兩個或多個線程適度操作某一控件的狀態(set value),則可能會迫使該控件進入一種不一致的狀態。還可能出現其他與線程相關的 bug,包括爭用和死鎖的情況。於是在調試器中運行應用程序時,如果創建某控件的線程之外的其他線程試圖調用該控件,則調試器會引發一個 InvalidOperationException
本文用一個很簡單的示例來講解這個問題(在窗體上放一個TextBox和一個Button,點擊Button後,在新建的線程中設置TextBox的值)
解決辦法一: 關閉該異常檢測的方式來避免異常的出現
經過測試發現此種方法雖然避免了異常的拋出,但是並不能保證程序運行結果的正確性 (比如多個線程同時設置TextBox1的Text時,很難預計最終TextBox1的Text是什麼)
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;
}
}
}
}
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();
}
}


{
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; }
}
}
}
}
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 Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.RunWorkerCompleted += SetTextBoxValue;
bw.RunWorkerAsync();
}
}
void SetTextBoxValue(object sender, RunWorkerCompletedEventArgs e) 
{
TextBoxSetValue tbsv = new TextBoxSetValue(this.textBox1, "Method3");
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;
}
}
}
}