15

コード ビハインドの関数を使用していて、ステータス バーに "Loading..." を表示するように実装したい場合は、次のようにすると理にかなっていますが、WinForms からわかるように、NoNo です。

StatusBarMessageText.Text = "Loading Configuration Settings...";            
LoadSettingsGridData();
StatusBarMessageText.Text = "Done";

WinForms Chapter 1 クラス 101 から、フォームは関数全体が完了するまでユーザーに変更を表示しないということです...つまり、「読み込み中」メッセージがユーザーに表示されることはありません。次のコードが必要です。

Form1.SuspendLayout();    
StatusBarMessageText.Text = "Loading Configuration Settings...";                
Form1.ResumeLayout();

LoadSettingsGridData();

Form1.SuspendLayout();    
StatusBarMessageText.Text = "Done";
Form1.ResumeLayout();

WPF でこの基本的な問題に対処するためのベスト プラクティスは何ですか?

4

3 に答える 3

35

最良かつ最も簡単:

using(var d = Dispatcher.DisableProcessing())
{
    /* your work... Use dispacher.begininvoke... */
}

または

IDisposable d;

try
{
    d = Dispatcher.DisableProcessing();
    /* your work... Use dispacher.begininvoke... */
} finally {
    d.Dispose();
}
于 2010-08-01T17:30:29.437 に答える
1

Shawn Wildermuth WPF Threads: Build More Responsive Apps With The Dispatcherの記事を読んでください。

私は、WindowsForms と同じようにバックグラウンド ワーカーを使用できると述べている以下に出くわしました。ファンシー:

BackgroundWorker Dispatcher がどのように機能するかを理解したところで、ほとんどの場合、Dispatcher を使用しないことに驚くかもしれません。Windows Forms 2.0 では、Microsoft は非 UI スレッド処理用のクラスを導入して、ユーザー インターフェイス開発者の開発モデルを簡素化しました。このクラスは BackgroundWorker と呼ばれます。図 7 は、BackgroundWorker クラスの一般的な使用法を示しています。

図 7 WPF での BackgroundWorker の使用

BackgroundWorker _backgroundWorker = new BackgroundWorker();

...

// Set up the Background Worker Events
_backgroundWorker.DoWork += _backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted += 
    _backgroundWorker_RunWorkerCompleted;

// Run the Background Worker
_backgroundWorker.RunWorkerAsync(5000);

...

// Worker Method
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // Do something
}

// Completed Method
void _backgroundWorker_RunWorkerCompleted(
    object sender, 
    RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        statusText.Text = "Cancelled";
    }
    else if (e.Error != null) 
    {
        statusText.Text = "Exception Thrown";
    }
    else 
    {
        statusText.Text = "Completed";
    }
}

BackgroundWorker コンポーネントは WPF とうまく連携します。これは、内部で AsyncOperationManager クラスを使用し、次に SynchronizationContext クラスを使用して同期を処理するためです。Windows フォームでは、AsyncOperationManager は、SynchronizationContext クラスから派生した WindowsFormsSynchronizationContext クラスを渡します。同様に、ASP.NET では、AspNetSynchronizationContext と呼ばれる SynchronizationContext の別の派生物で動作します。これらの SynchronizationContext 派生クラスは、メソッド呼び出しのクロススレッド同期を処理する方法を知っています。

WPF では、このモデルは DispatcherSynchronizationContext クラスで拡張されます。BackgroundWorker を使用すると、Dispatcher が自動的に採用され、クロススレッド メソッド呼び出しが呼び出されます。幸いなことに、この一般的なパターンには既に慣れているので、新しい WPF プロジェクトで引き続き BackgroundWorker を使用できます。

于 2008-09-18T00:55:59.013 に答える
-1

これを機能させる最も簡単な方法は、LoadSettingsGridData をディスパッチャー キューに追加することです。操作の DispatcherPriority を十分に低く設定すると、レイアウト操作が発生し、問題なく使用できます。

StatusBarMessageText.Text = "Loading Configuration Settings...";
this.Dispatcher.BeginInvoke(new Action(LoadSettingsGridData), DispatcherPriority.Render);
this.Dispatcher.BeginInvoke(new Action(() => StatusBarMessageText.Text = "Done"), DispatcherPriority.Render);
于 2008-09-17T13:32:18.423 に答える