c# Thread プログラミング

【C#】解決策|有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール がアクセスされました。

こんな例外がでて困ってる!

有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'textBox1' がアクセスされました。'

 

フォームに配置したTextBoxなどのコントロールを更新しようとして、上記のような例外が発生する場合があります。

これを解決します。


有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール がアクセスされました。【原因】

【原因】別スレッドからコントロールへアクセスしたため

Windowsフォームのコントロールは、必ずコントロールを生成したスレッドから行う必要があります。

※コントロールを生成したスレッド:メインスレッド

 

上記の例外が発生している方は、スレッドを作成してそのスレッドからコントロールへアクセスしていませんか?

それが、例外発生の原因です。

 

対策は簡単です。

以下にコードを示します。

Invokeメソッドを使ってコントロールへアクセスする

動作確認用画面を作成

動作確認用の画面はこんな感じ(単純です)。

Invokeメソッドを使用する

ボタンをクリックすると、その下のTextBoxに「Update」と表示するだけのもの。

ソースコード例

ソースコードは以下の通り。

ダメな例(例外が発生する)、良い例を一緒に記載しています。

※「bool error = true;」を true or false に変えると、それぞれ動作確認できます。

ダメな例:例外発生「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール がアクセスされました。」

「bool error = true;」にして実行してみます。

ボタンをクリックすると、このように例外が発生します。

有効でないスレッド間の操作

この例では、「Task.Factory.StartNew」で別スレッドを生成して、そこからコントロールにアクセスしようとしているためです。

良い例:Invokeメソッドを使用する

この部分です。

this.Invoke(new Action(this.UpdateText));

これで、メインスレッドからコントロールにアクセスできるようになります。

簡単ですね。

Invokeが必要か確認する方法

この例では、Invokeメソッド呼ぶ前にこんなif文を実行しています。

if (this.InvokeRequired)

これは、Invokeが必要なのか確認するメソッドです。

必要な場合(別スレッドからアクセスしようとしている)は、「InvokeRequired」がtrueで返ります。

不要な場合(メインスレッドでアクセスしようとしている)は、「InvokeRequired」がfalseで返ります。

まとめ

  • 別スレッドからのコントロールへのアクセスはNG
  • Invokeメソッドを使って解決
  • InvokeRequiredでInvokeメソッドの要否を確認

\この記事はどうでしたか?/

-c#, Thread, プログラミング

© 2021 ジョブログLiFE