Windowsフォームアプリでは、Task.Run()など別スレッドから、メインスレッドのフォームコントールを操作すると、「System.InvalidOperationException: ‘有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール がアクセスされました。’」Exceptionが発生しますが、Invoke()を通すことで解消します。
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-6.png)
Invoke()を通すことで解消します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private void button3_Click(object sender, EventArgs e) { Task.Run(() => { var value = "ccccc"; Invoke(() => { textBox1.Text = value; }); }); } |
ソースコードはGitHubで公開しています。
ソースコード構成
今回使った Visual Studio プロジェクト テンプレートは、Visual Studio 2022 + .NET 6.0 の Windowsフォームアプリです。
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-4.png)
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-5.png)
テンプレートに対して、下記の処理を加えました。
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-7.png)
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-8.png)
ソースコード変更内容を解説
3パターンの実装で、テキストボックスに値を設定するボタンを3つ追加。
・button1は、メインスレッドからメインスレッドへ値を設定し、正常終了。
・button2は、別スレッドからメインスレッドへ値を設定し、Exception発生
・button3は、別スレッドからメインスレッドへ Invokeを通して値を設定し、正常終了。
/Form1.cs
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-10.png)
![](https://blog.unikktle.com/wp-content/uploads/2023/02/image-9-1024x617.png)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
namespace WinFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { textBox1.Text = "aaaaa"; } private void button2_Click(object sender, EventArgs e) { Task.Run(() => { textBox1.Text = "bbbbb"; }); } private void button3_Click(object sender, EventArgs e) { Task.Run(() => { var value = "ccccc"; Invoke(() => { textBox1.Text = value; }); }); } } } |
コメント