2011-02-09 23 views
1

BackgroundWorkerからReportProgressのデータを受け取るListViewコントロールがあります。作業者は約100行をすばやく連続してダンプします。各データチャンクはProgressChangedイベントとGUIスレッドはListViewに新しい項目を追加します。BackgroundWorkerでデータを読み込み中にGUIがフリーズする

データ取得操作が別のスレッドで実行されるため、GUIはすべての変更時に更新されるはずです。しかし何らかの理由でそれは起こりません。作業者が完了するまでインターフェイスはフリーズしたままです。

アイデア?

また、テストは非常に高速なマシン上で行われるため、コンピュータのパフォーマンスは問題ではないと思います。

これはWinFormsアプリケーションです。

+0

SOmeコードスニペットをご覧ください。 – Aliostad

+0

WPFまたはWindowsフォームも参照してください。 – Aliostad

+0

WinForms。このコードには、Worker.ReportProgress(25、newItem)とListView1.Items.Add(item.DisplayName)のような特別なものはありません。 – SharpAffair

答えて

3

ReportProgressコールの後、あなたのBGWワーカーループでこれを入れて:

System.Threading.Thread.Sleep(15); 

オッズをあなたは今、リストビューの更新を参照してくださいすることをいいます。ここで起こっているのは、UIスレッドがデリゲートの呼び出し要求でいっぱいになっているということです。ペイント通知の前に常にディスパッチされます。 次の呼び出し要求が、前の呼び出し要求が実行を終了する前に到着した場合、通常のハウスキーピングタスクを実行することは決してありません。絵を描き、入力に反応するように。アイテムは実際にはリストビューに追加されますが、表示されていないだけです。

ReportProgressの呼び出し回数が少なくなります。毎秒25回以上それを行うことはリソースの無駄です、人間は違いを見ることができません。 BGWがList <>に項目を格納させ、AddRange()を呼び出してUIスレッドのオーバーヘッドを削減します。

+0

それは動作します。しかし、プロセスはPCのパフォーマンスに依存します。遅いマシン遅延の場合は、より高い必要があります。パフォーマンスに依存しない方法はありますか?私はおそらくApplication.DoEventsハウスキーピングが完了したが、今StackOverflowException(ハァッ)を取得中に待機するのに役立つと思った。 – SharpAffair

+0

1秒間に25回は人間の数で、どのマシンでも十分です。少なくとも40ミリ秒が経過するまでReportProgressを呼び出さないでください。 DateTime.Nowはそれを測定するためにうまくいきます、あなたは毎秒〜21の更新を得るでしょう。 –

+1

私はちょうど1年前に書いたフォームからこのコードを取り出しました。「なぜ地球上で私はここでそれを寝かせるのですか?」この質問へのあなたの答えを読む私は最初になぜそれをしたのか思い出しています。 "Oooooooh、そう。最後のProgressChangedイベントに追いつくのに時間が必要だ」 –

0

ListViewに行を1つずつ追加すると、高速なマシンでもフリーズが発生します。

人口処理の前後にListView.SuspendLayout()ListView.ResumeLayout()を呼び出してみてください。

+0

ちょうどそれを試みた - 助けていないようです。私はこれを行う多くのプログラムを見てきました - 彼らは別のスレッドで標準ListViewをロードし、すべての変更を更新します。 – SharpAffair

1

Addの代わりにAddRangeを使用してListView1.Itemsにアイテムをバッチロードすることができます。中間配列を塗りつぶして、AddRangeとともに使用してください。

+1

この主なポイントは、負荷全体が完了するまで待つことなく、ユーザーにデータを表示することです。 – SharpAffair

+0

@スフィンクス - 私は数多くの小さなバッチを考えていました。私の経験では、Winformsのリストビューのパフォーマンスはあまり良くありません。 – Andrew

関連する問題