これは良い(またはまともな)理由があると確信しています。それは何ですか?WinFormsでは、なぜ他のスレッドからUIコントロールを更新できないのですか?
答えて
他の問題の中でも、デッドロックが発生する可能性があります。
例では、セカンダリスレッドがUIコントロールを更新しようとしている可能性がありますが、UIコントロールはセカンダリスレッドによってロックされたリソースが解放されるのを待っているため、他の人がコメントしたように、この状況はUIコードに固有のものではなく、特に一般的です。
C++などの他の言語では、WinFormsのように例外をスローすることなく自由に試してみることができますが、デッドロックが発生した場合にアプリケーションがフリーズして応答を停止することがあります。
ちなみに、UIスレッドにコントロールを更新することを簡単に伝えることができます。単にデリゲートを作成し、デリゲートを渡す(非同期の)BeginInvokeメソッドを呼び出します。例えば。
myControl.BeginInvoke(myControl.UpdateFunction);
この
は、デバッグ中にスローされた1.0/1.1例外なくでコントロールを同時に更新しようとするものは2つありません。 (これは、CPUが書き込み/読み取りの途中で他のスレッドに切り替えた場合に発生する可能性があります) 複数のスレッド間で共有変数にアクセスするときに、mutexを使用する必要があるのと同じ理由があります。
編集:あなたがしようとすると( リサイズのようにスローされ 例外なく)これを行うことが 自由であるC++などの他の言語で
が、あなたは ハードを学んで終わるだろう方法!
が
ああはい...私はC/C++とC#の間で切り替えるため、もう少し汎用的だったし、私はしてきたはずです、申し訳ありません...彼は/あなたはCでこれをを行うことができ、正確ですC + +、しかしそれはあなたをかむために戻ってくる!
戻るワーカースレッドからC++/MFCのPostMessageを行うと等価である、あなたが得たものの代わりに断続的な実行時ぶら下がっシナリオでした。ニース! :) したがって、2.0では、このシナリオは例外をスローし、かなり正しかったのです。
実際の理由は、(Adam Haileのように)何らかの並行性/ロック問題です。 通常の.NET API(TextBox.Text = "Hello";など)は、アクションが更新されたスレッドとは別のスレッドで実行されると問題を発生させるSENDコマンド(即時アクションが必要)をラップします。 Invoke/BeginInvokeを使用すると、アクションをキューに入れる代わりにPOSTが使用されます。
詳細については、hereを参照してください。
同時に呼び出されることに敏感な更新関数内で同期を実装する必要もあります。これをUI要素に対して行うと、アプリケーションレベルとOSレベルでコストがかかり、大部分のコードでは完全に冗長になります。
一部のAPIは、あなたができるように、一時的に(または永久に)システムの現在のスレッドの所有権を変更する方法を提供し、スレッド間の通信に頼る必要なく、他のスレッドからのシステムを更新します。
これはすばらしい質問だと思います。より良い回答が必要だと思います。
確かに唯一の理由は、スレッドセーフではないフレームワークのどこかにフレームワークに何かがあることです。 .NETやWin32には問題がありますか?そして、なぜ私に何が厄介な回避策のように感じるのかを強制するのではなく、ソースを修正するプッシュはありませんか?
本当の根本的な問題はどこにいるのですか?
私はこれは素晴らしい質問だと思う - と私はより良い 答えの必要があると思います。
確かに唯一の理由は、 がフレームワークのどこかにあります。 はスレッドセーフではありません。
「何か」は、System.Windows.Forms内のすべてのコントロールのほとんどすべての単一インスタンスメンバーです。
System.Windows.Forms内の多くのコントロールのMSDNドキュメント(すべてではない場合)"この型のpublic static(Visual BasicではShared)メンバはすべてスレッドセーフです。スレッドセーフです。 "
これは、TextBox.Text {get; set;}
としてインスタンスメンバーがリエントラントないことを意味します。
これらのインスタンスメンバーをスレッドセーフにすると、ほとんどのアプリケーションで必要としないオーバーヘッドが発生する可能性があります。代わりに.Netフレームワークの設計者は、複数のスレッドからフォームコントロールへのアクセスを同期させる負担がプログラマに課せられるべきだと正しく判断しました。
[編集]
ここでは、「どのように」説明して記事へのリンクである「なぜ」この質問のみ尋ねるものの:
方法:コントロールをWindowsフォームにしてくださいスレッドセーフコールそれが合理的ジョンズの答えが聞こえるが、MSDN
にリエントラントでスレッドセーフではないことは完全に可能です。 (f)=> {x + = 1; f(x) x - = 1; }これは、f(x)が1つのスレッドでラムダに再び入るが、マルチスレッドの場合にはxに競合するとオーバーフローするまでは問題ない。 –
私はかなり待っているバーのような進歩コントロールがあると、別のスレッドから値を更新することができます。
- 1. 他のスレッドは私のREF更新をなぜ見ないのですか?
- 2. なぜ私は自分のスレッドで自分のUIを更新できないのですか?
- 3. AndroidのUIスレッドのみがUIを更新できるのはなぜですか?
- 4. 非同期操作でループ中にWinformsのUIを更新できるのはなぜですか?
- 5. WinForms UIを更新するBackgroundWorkerスレッド
- 6. WPFの異なるスレッドからUIコントロールを更新するときに「別のスレッドが所有しているため、このオブジェクトにアクセスできない」エラー
- 7. angle-ui-gridのgridApi.on.edit.beginCellEditで新しいドロップダウンオプションを即座に更新できないのはなぜですか?
- 8. APIからカスタムリストビューを更新できないのはなぜですか?
- 9. 他のスレッドからUIを更新する
- 10. 他のスレッドからUIを更新する
- 11. ナビゲーションバー(PermanentSlot)を更新できないのはなぜですか?
- 12. iOSコントロールで画像が更新されないのはなぜですか?
- 13. なぜコントロールの一部のプロパティを別のスレッドから更新するのが安全ですか?
- 14. 非UIスレッドがビュープロパティを変更できないのはなぜですか?アンドロイドで
- 15. なぜデータをフォームで更新できないのですか?
- 16. なぜdbContextでレコードを更新できないのですか?
- 17. なぜデータを更新できないのですか?
- 18. なぜui-routeはstate1をstate2から解決できないのですか?
- 19. UIの更新コードからのスレッド
- 20. 私のUIが更新されないのはなぜですか?
- 21. AsyncTaskからUIを更新できない
- 22. スレッドをUIから更新する
- 23. 別のメインでないスレッドからQGraphicsSceneを更新する
- 24. 他のクラスからのWinFormコントロールのスレッドセーフな更新
- 25. UIスレッドからSerialDevice.FromIdAsyncを開く必要があるのはなぜですか?
- 26. WPF UIコントロールに対するマルチスレッドアクセスのオーバーヘッドはなぜですか?
- 27. ThreadPoolは他のスレッドのコントロールに直接アクセスできますか?
- 28. なぜjQuery UIダイアログから送信ボタンをトリガーできないのですか?
- 29. 新しいスレッドで新しいRunnableを書くのはなぜですか?
- 30. SQLiteでステートメントを更新できないのはなぜですか?
なぜこの回答が受け入れられたのか分かりません。これは単に正解ではありません。デッドロックは、複数のスレッドを持つたびに発生します。 GUIプログラムには、それが起こりやすくなるものは何もありません。さらに、BeginInvoke()を使用しても簡単に実行できます。 Brian Ensinkの答えが正しいです。 – mhenry1384
-1:ロックされたリソースを待つことは問題ではありません。問題は、マルチスレッド環境で使用するように設計されていないコードで大量に存在する競合状態です。 [CheckForIllegalCrossThreadCalls](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls(VS.80).aspx)をfalseに設定することでこれを確認し、デッドロックを観察することもできます何か面白いことが起こるまで、フリーの操作。 –