2008-08-13 5 views

答えて

10

他の問題の中でも、デッドロックが発生する可能性があります。

例では、セカンダリスレッドがUIコントロールを更新しようとしている可能性がありますが、UIコントロールはセカンダリスレッドによってロックされたリソースが解放されるのを待っているため、他の人がコメントしたように、この状況はUIコードに固有のものではなく、特に一般的です。

C++などの他の言語では、WinFormsのように例外をスローすることなく自由に試してみることができますが、デッドロックが発生した場合にアプリケーションがフリーズして応答を停止することがあります。

ちなみに、UIスレッドにコントロールを更新することを簡単に伝えることができます。単にデリゲートを作成し、デリゲートを渡す(非同期の)BeginInvokeメソッドを呼び出します。例えば。

myControl.BeginInvoke(myControl.UpdateFunction); 

この

は、デバッグ中にスローされた1.0/1.1例外なくで

+3

なぜこの回答が受け入れられたのか分かりません。これは単に正解ではありません。デッドロックは、複数のスレッドを持つたびに発生します。 GUIプログラムには、それが起こりやすくなるものは何もありません。さらに、BeginInvoke()を使用しても簡単に実行できます。 Brian Ensinkの答えが正しいです。 – mhenry1384

+1

-1:ロックされたリソースを待つことは問題ではありません。問題は、マルチスレッド環境で使用するように設計されていないコードで大量に存在する競合状態です。 [CheckForIllegalCrossThreadCalls](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.checkforillegalcrossthreadcalls(VS.80).aspx)をfalseに設定することでこれを確認し、デッドロックを観察することもできます何か面白いことが起こるまで、フリーの操作。 –

1

コントロールを同時に更新しようとするものは2つありません。 (これは、CPUが書き込み/読み取りの途中で他のスレッドに切り替えた場合に発生する可能性があります) 複数のスレッド間で共有変数にアクセスするときに、mutexを使用する必要があるのと同じ理由があります。

編集:あなたがしようとすると( リサイズのようにスローされ 例外なく)これを行うことが 自由であるC++などの他の言語で

が、あなたは ハードを学んで終わるだろう方法!

ああはい...私はC/C++とC#の間で切り替えるため、もう少し汎用的だったし、私はしてきたはずです、申し訳ありません...彼は/あなたはCでこれをを行うことができ、正確ですC + +、しかしそれはあなたをかむために戻ってくる!

2

戻るワーカースレッドからC++/MFCのPostMessageを行うと等価である、あなたが得たものの代わりに断続的な実行時ぶら下がっシナリオでした。ニース! :) したがって、2.0では、このシナリオは例外をスローし、かなり正しかったのです。

実際の理由は、(Adam Haileのように)何らかの並行性/ロック問題です。 通常の.NET API(TextBox.Text = "Hello";など)は、アクションが更新されたスレッドとは別のスレッドで実行されると問題を発生させるSENDコマンド(即時アクションが必要)をラップします。 Invoke/BeginInvokeを使用すると、アクションをキューに入れる代わりにPOSTが使用されます。

詳細については、hereを参照してください。

1

同時に呼び出されることに敏感な更新関数内で同期を実装する必要もあります。これをUI要素に対して行うと、アプリケーションレベルとOSレベルでコストがかかり、大部分のコードでは完全に冗長になります。

一部のAPIは、あなたができるように、一時的に(または永久に)システムの現在のスレッドの所有権を変更する方法を提供し、スレッド間の通信に頼る必要なく、他のスレッドからのシステムを更新します。

0

これはすばらしい質問だと思います。より良い回答が必要だと思います。

確かに唯一の理由は、スレッドセーフではないフレームワークのどこかにフレームワークに何かがあることです。 .NETやWin32には問題がありますか?そして、なぜ私に何が厄介な回避策のように感じるのかを強制するのではなく、ソースを修正するプッシュはありませんか?

本当の根本的な問題はどこにいるのですか?

23

私はこれは素晴らしい質問だと思う - と私はより良い 答えの必要があると思います。

確かに唯一の理由は、 がフレームワークのどこかにあります。 はスレッドセーフではありません。

「何か」は、System.Windows.Forms内のすべてのコントロールのほとんどすべての単一インスタンスメンバーです。

System.Windows.Forms内の多くのコントロールのMSDNドキュメント(すべてではない場合)"この型のpublic static(Visual BasicではShared)メンバはすべてスレッドセーフです。スレッドセーフです。 "

これは、TextBox.Text {get; set;}としてインスタンスメンバーがリエントラントないことを意味します。

これらのインスタンスメンバーをスレッドセーフにすると、ほとんどのアプリケーションで必要としないオーバーヘッドが発生する可能性があります。代わりに.Netフレームワークの設計者は、複数のスレッドからフォームコントロールへのアクセスを同期させる負担がプログラマに課せられるべきだと正しく判断しました。

[編集]

ここでは、「どのように」説明して記事へのリンクである「なぜ」この質問のみ尋ねるものの:

方法:コントロールをWindowsフォームにしてくださいスレッドセーフコールそれが合理的ジョンズの答えが聞こえるが、MSDN

http://msdn.microsoft.com/en-us/library/ms171728.aspx

+1

リエントラントでスレッドセーフではないことは完全に可能です。 (f)=> {x + = 1; f(x) x - = 1; }これは、f(x)が1つのスレッドでラムダに再び入るが、マルチスレッドの場合にはxに競合するとオーバーフローするまでは問題ない。 –

7

正しくありません。実際にはInvokeを使用していてもデッドロック状態にならない安全ではありません。 Invokeを使用してバックグラウンドスレッドで発生したイベントを処理すると、この問題が発生することさえあります。


本当の理由は、レースの条件で行うことがより多くを持っており、古代のWin32時代に戻って産みます。ここで詳細を説明することはできません。キーワードはメッセージポンプ、WM_PAINTイベント、「SEND」と「POST」の微妙な違いです。


詳しい情報は、こちらをherehere見つけることができます。

0

私はかなり待っているバーのような進歩コントロールがあると、別のスレッドから値を更新することができます。

関連する問題