別のスレッドからUI要素を更新するグーグル/ここにたくさんのスレッドがあります。
チェックボックスの値だけを取得したい場合はどうなりますか?
特別なことをしなくてもこれを行うことはできますか?
別のスレッドからUI要素を更新するグーグル/ここにたくさんのスレッドがあります。
チェックボックスの値だけを取得したい場合はどうなりますか?
特別なことをしなくてもこれを行うことはできますか?
編集:前に書いたものを取り戻さなければならないようです。次のことを試しました。
と呼ばれるテキストボックスを追加し、プロパティmyTextBox
の値を取得しようとしました。Text
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
string value = myTextBox.Text;
Thread.Sleep(2000);
});
t.Start();
そして、アプリ(WPF)が2秒後にクラッシュするようです。ディスパッチャの使用は機能します:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
myTextBox.Dispatcher.BeginInvoke(
(Action)(() => { string value = myTextBox.Text; }));
Thread.Sleep(2000);
});
t.Start();
したがって、少なくともWPFでは、GUIコンポーネントから値を読み取るときに、ディスパッチャスレッドを通過する必要があります。
2番目の編集:これは良くなります。Text
どうやら古典的なWinFormsの実験を繰り返すと、を使用せずにプロパティを読み取ることができることがわかりInvoke/BeginInvoke
ます。興味深いことに、プロパティの設定も(呼び出しなしで)正常に機能するようですが、スレッドセーフではなく、アプリが何らかの理由で文句を言わないことを賭けます。
結論:他のスレッドからのGUIコンポーネントと対話するときは、ディスパッチャーを使用することをお勧めします。これにより、読み取り/書き込みが単一のスレッドにシリアル化され、スレッドセーフの問題が発生しなくなります。
別のスレッドからUI要素にアクセスできますか?(設定されません)?
いいえ。
これが取引です。UI要素には、非常に厳密なスレッドアフィニティ要件があります。これは、要素をホストしているスレッドからのみ要素にアクセスできることを意味します。これには、単純な読み取りを含むすべての種類のアクセスが含まれます。1
単純なプロパティゲッターには問題なく機能する可能性がありますが、その安全性の認識は、特定の制御が実装された方法の偶発的な結果です。インスタンスにはスレッドアフィニティがあるためControl
、スレッドローカルストレージ技術を使用して状態の一部を保存できる可能性がありますが、もちろん、別のスレッドとは互換性がありません。または、読み取ろうとしている値が中途半端な状態にある場合はどうなりますか?書き込みは制御できないコード内で発生している可能性があるため、その読み取りへのアクセスを同期する方法はありません。それでも、これは発生する可能性のある微妙なメモリバリアの問題を無視しています。
繰り返しますが、それが機能しているように見える場合は、事故としてチョークで書きます。UI要素をホストしているスレッドよりもスレッドからUI要素にアクセスすることは、災害のレシピです。物事は予期せず、見事に失敗する可能性があります。
1この規則にはほとんど例外がありません。メソッドの使用ISynchronizeInvoke
はそのような例外の1つです。
厳密には、スレッドセーフではありません。たとえば、プロパティGetコードが複数の操作で構成されている場合、UIスレッドは、Get操作の途中で動作し、予期しない結果を引き起こす可能性があります。
通常どおりに値を読み取るだけです。コントロールを更新するためだけに、GUIスレッドに切り替える必要があります。