本サイトはアフィリエイト広告を使用しています

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# 初心者におすすめの参考書

  • はじめの1冊に最適
  • 手元に置いておきたい独習シリーズ
created by Rinker
¥490 (2024/11/23 07:20:34時点 Amazon調べ-詳細)
  • 名著。技術屋なら必読。繰り返しよむことで確実にレベルアップ。

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