UIスレッドのデットロック
- 題名: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/04 21:42:58
- ID: 30520
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[1]: UIスレッドのデットロック
- 著者: Azulean
- 日時: 2012/06/05 0:58:20
- ID: 30522
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[1]: UIスレッドのデットロック
- 著者: shu
- 日時: 2012/06/05 10:44:49
- ID: 30525
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[2]: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/05 12:53:47
- ID: 30533
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[2]: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/05 13:20:33
- ID: 30535
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[3]: UIスレッドのデットロック
- 著者: shu
- 日時: 2012/06/06 8:05:17
- ID: 30540
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[4]: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/06 11:11:16
- ID: 30542
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[5]: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/06 11:37:08
- ID: 30543
- この記事の返信元:
- この記事への返信:
- ツリーを表示
- 題名: Re[6]: UIスレッドのデットロック
- 著者: unripe01
- 日時: 2012/06/06 11:38:49
- ID: 30544
- この記事の返信元:
- この記事への返信:
- ツリーを表示
分類:[.NET]
いつもお世話になっております。
マルチスレッドでのUI操作における
UIスレッドのデットロックについて
ご鞭撻いただきたく書き込みさせていただきました。
非同期操作、かつ並列処理で、UI上のテキストボックスにテキストを追加する検証を行っています。
特定の非同期操作でUIスレッドのデッドロック?が発生しているように思えるのですが
デッドロックとなる原因・理由が理解できず、悩んでおります。
非同期のスレッド操作について、ご指導いただければ幸いです。
下部にソースコードを記載していますが
理解できていない箇所の要点です。
・BeginInvoke・Invokeを使ってTextBoxの内容を変更しようとするメソッドを
パラレルで呼び出すとフリーズする。(時がある)
フリーズのタイミング
1.Invoke呼び出し ⇒ほとんどフリーズする。プールスレッドのスレッド不足?
2.BeginInvoke呼び出し TextBoxの描画中にUIスレッド上からマウスでTextBoxをクリックするとフリーズする(これは多分デッドロック)
1については、並列処理数をかなり減らしてもフリーズするため、スレッドプールの不足とは考えにくく、
どういったスレッドの処理によって、フリーズしてしまうのかすら検討がつけれていません。
2については、UIからの操作と、非同期操作間で何らかのデッドロックが発生していると思うのですが、
同期操作にすると1と同じ現象になってしまうので、解消方法が見つけれていません。
対策として、スレッドを別に立ち上げて(new Thread)BeginInvoke操作を実行すると問題なく作動するのですが・・・
果たして、正しいお作法なのか・・・
(2でデッドロックするのに、別スレッドからの操作をして同期をとらなくても大丈夫なのかな・・・等)
別スレッドで操作する際のUIに対する処理のベストプラクティス等あれば教えていただきたいです。
(バックグラウンドワーカーの内部処理でイベントを使っているようですが、これが正なのでしょうか?)
恐れ入りますが、よろしくお願い致します。
開発言語 C# 4.0
環境 VisualStudio 2010
プロジェクト:
Windows From
├ textBox1(テキストボックス)
├ 各種処理実行するためのボタン
以下、処理の説明。
1.マニュアルスレッドを使った非同期処理かつバックグラウンド処理(New Thread)。
//これは動く。
2.プールスレッドを使った非同期処理(BeginInvoke)
//実行中にTextBoxを触るとフリーズ。
3.プールスレッドを使った同期処理(Invoke)
//フリーズする。
※123いずれも並列処理を行い、途中に重たい処理を想定してThread.Sleepしている。
内部で以下のメソッドを呼び出して、TextBoxを更新している。
4.textBox1.BeginInvokeを使ったTextを変更するメソッド。EndInvokeを呼ばず、同期は待たない(12で利用)
5.textBox1.Invokeを使ったTextを変更するメソッド(3で利用)
-----実装コード-----
/// マニュアルスレッドにより実行
/// 一番安定している。(お作法として正しいか?)
private void button1_Click( object sender, EventArgs e )
{
//マニュアルスレッド・バックグラウンドでパラレル処理実行
var t = new Thread( () => {
Parallel.For( 0, 20, id => {
AddMsgUseBeginInvoke( id + "開始" );
System.Threading.Thread.Sleep( 300 );
AddMsgUseBeginInvoke( id + "終了" );
});
} );
t.IsBackground = true;
t.Start();
}
/// プールスレッドを使った非同期処理。待たない。
private void button2_Click( object sender, EventArgs e )
{
Parallel.For( 0, 20, id => {
AddMsgUseBeginInvoke( id + "開始" );
System.Threading.Thread.Sleep( 300 );
AddMsgUseBeginInvoke( id + "終了" );
} );
}
/// プールスレッドを使った同期
private void button3_Click( object sender, EventArgs e )
{
Parallel.For( 0, 20, id => {
AddMsgUseInvoke( id + "開始" );
System.Threading.Thread.Sleep( 300 );
AddMsgUseInvoke( id + "終了" );
} );
}
/// BeginInvokeを使ったTextBox再描画処理
private void AddMsgUseBeginInvoke( string msg )
{
IAsyncResult sync =
textBox1.BeginInvoke( new MethodInvoker( () => {
textBox1.Text += msg + " - 1" + "\r\n";
textBox1.Text += msg + " - 2" + "\r\n";
textBox1.Text += msg + " - 3" + "\r\n";
textBox1.Text += msg + " - 4" + "\r\n";
textBox1.Text += msg + " - 5" + "\r\n";
textBox1.Refresh();
}
) );
//ここのコメントを外すとInvokeと同じ
//textBox1.EndInvoke( sync );
}
/// Invokeを使ったTextBox再描画処理。
private void AddMsgUseInvoke( string msg )
{
//デッドロックする
//スレッドプールが足りずに発生している?
textBox1.Invoke( new MethodInvoker( () => {
textBox1.Text += msg + " - 1" + "\r\n";
textBox1.Text += msg + " - 2" + "\r\n";
textBox1.Text += msg + " - 3" + "\r\n";
textBox1.Text += msg + " - 4" + "\r\n";
textBox1.Text += msg + " - 5" + "\r\n";
textBox1.Refresh();
}
) );
}