有効ではないスレッド間の操作(C#/VB.NET)
2010年10月29日
"有効ではないスレッド間の操作"と言う例外が発生する事があります。原因はFromとは別のスレッドからFrom上のコントロールにアクセスしたからです。しかし、あるオマジナイをすると例外が発生しなくなります。
このサンプル(ソース/コード)は、MyProc1を呼び出すスレッドを作成すると例外が発生します。MyProc2を呼び出すスレッドを作成すると例外は発生しません。
' -----------------------------------------------------------
' 有効ではないスレッド間の操作のサンプル(VB.NET/VS2005)
Private MyThread As System.Threading.Thread
Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' スレッド開始
MyThread = New System.Threading.Thread( _
New System.Threading.ThreadStart(AddressOf MyProc1))
MyThread.Start()
End Sub
Private Sub Form1_FormClosed( _
ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.FormClosedEventArgs) _
Handles MyBase.FormClosed
' スレッド終了
MyThread.Abort()
End Sub
' 例外が発生するサンプル
Private Sub MyProc1()
Do While (True)
System.Threading.Thread.Sleep(1000)
TextBox1.Text = "abc" ' ここで例外が発生する
' エラーメッセージ
' "有効ではないスレッド間の操作:
' コントロールが作成されたスレッド以外の
' スレッドからコントロール 'TextBox1' が
' アクセスされました。"
Loop
End Sub
' 例外が発生しないサンプル
Private Delegate Sub D_UpdTextBox(ByVal txt As String)
Private Sub MyProc2()
Do While (True)
System.Threading.Thread.Sleep(1000)
TextBox1.Invoke( _
New D_UpdTextBox(AddressOf UpdTextBox), "abc")
Loop
End Sub
Private Sub UpdTextBox(ByVal txt As String)
TextBox1.Text = txt
End Sub
' -----------------------------------------------------------
// ----------------------------------------------------------
// 有効ではないスレッド間の操作のサンプル(C#.NET/VS2005)
private System.Threading.Thread MyThread;
private void Form1_Load(
object sender, EventArgs e)
{
// スレッド開始
MyThread = new System.Threading.Thread(
new System.Threading.ThreadStart(MyProc1));
MyThread.Start();
}
private void Form1_FormClosed(
object sender, FormClosedEventArgs e)
{
// スレッド終了
MyThread.Abort ();
}
// 例外が発生するサンプル
private void MyProc1()
{
while (true)
{
System.Threading.Thread.Sleep(1000);
textBox1.Text = "abc"; // ここで例外が発生する
// エラーメッセージ
// "有効ではないスレッド間の操作:
// コントロールが作成されたスレッド以外の
// スレッドからコントロール 'textBox1' が
// アクセスされました。"
}
}
// 例外が発生しないサンプル
private delegate void D_UpdTextBox(String txt);
private void MyProc2()
{
while (true)
{
System.Threading.Thread.Sleep(1000);
textBox1.Invoke(
new D_UpdTextBox(UpdTextBox), "abc");
}
}
private void UpdTextBox(String txt)
{
textBox1.Text = txt;
}
// ----------------------------------------------------------