2011-01-27 10 views
0

私はバックグラウンドで多くのタスクを実行するwpfアプリケーションを作成していますが、UIは応答性があり、さまざまなバックグラウンドタスクのステータスを表示する必要があります。また、UIをまったく表示しないオプションもあります。この場合、メインフォームのインスタンスをまったく作成せずにステータスメッセージを破棄する必要があります。私がしようとしてきた何バックグラウンドスレッドの情報でWPFウィンドウを更新するにはどうすればよいですか?

がApp.xamlから

StartupUri="MainWindow.xaml"

を削除することです。その後、App.xaml.csでは、私はこれが必要な場合は、メインフォームを示しており、すべてのバックグラウンド・プロセスを開始し

`

public App() 
    { 
     Startup += new StartupEventHandler(App_Startup); 
    } 

    void App_Startup(object sender, StartupEventArgs e) 
    { 
     // Code which loads application settings is here 

     if (pf.ShowUI) 
     { 
      MainWindow mainWindow = new MainWindow(); 
      mainWindow.Show(); 
     } 

     // The background processes will begin here. 

    }` 

を持っています。この部分は動作します。

UIにバックグラウンドからのメッセージを送信するためには、私は非常に基本的なメッセンジャー実装しました:

`

internal interface IMessageHandler 
{ 
    void ReceiveMessage(string message); 
} 

internal class Messenger 
{ 
    private static List<IMessageHandler> _handlers; 

    internal static void AddHandler(IMessageHandler handler) 
    { 
     _handlers.Add(handler); 
    } 

    internal static void RemoveHandler(IMessageHandler handler) 
    { 
     try 
     { 
      _handlers.Remove(handler); 
     } 
     catch (Exception ex) {} 
    } 

    internal static void Broadcast (string message) 
    { 
     foreach (IMessageHandler handler in _handlers) 
     { 
      handler.ReceiveMessage(message); 
     } 
    } 
}` 

をメインフォームはIMessageHandlerインタフェースを実装し、に自分自身を追加します起動時のハンドラとしてのメッセンジャー。メインフォームにステータスを送信する必要があるプロセスは、メッセンジャーのBroadcastメソッドを呼び出すだけです。

私が抱えている問題は、バックグラウンドプロセスが完了するまでメッセージがフォームに表示されず、UIがロックされていることです。なぜ私のバックグラウンド・プロセスは、私のUIを凍結している

`

public void ReceiveMessage(string message) 
    { 
     Dispatcher.Invoke(DispatcherPriority.Normal, 
       new Action<string>(AddText), 
       message); 
    } 

    private void AddText(string text) 
    { 

     Label myLabel = new Label(); 
     myLabel.Content = text; 
     stackPanel1.Children.Add(myLabel); 
     if (stackPanel1.Children.Count > 5) 
     { 
      stackPanel1.Children.RemoveAt(0); 
     } 
    }` 

次のように

受信メッセージを処理するUIのコードはありますか?それを防ぐために私は何ができますか?そして、私のUIがステータスメッセージで更新されないのはなぜですか?

+0

パターンをMVVMとして使用して、ビューをモデルデータにバインドすることを検討してください。 – HyLian

答えて

1

私は非常に同じ問題を抱えており、this blog postは私にそれを解決するのを助けました。

+0

私はバックグラウンドスレッドを明示的に新しいスレッドとして起動する必要があったようです。私は、App_Startupメソッドの終わりからUIに別のスレッド上にあると呼んでいると仮定しました。これはそうではないようです。新しいスレッドでプロセスを起動するとすぐに、他のすべてのパーツは予想どおりに機能しました。リンクありがとう。 – RichieACC

+0

ありがとう、それがあなたの問題を解決したことを幸せ。 – Asha

0

多分これはあなたの問題である:あなたがInvokeを使用する場合、この方法が実行されますと、アプリケーションがそれが完了するのを待って、しかしであるため

Dispatcher.Invoke(DispatcherPriority.Normal, 
       new Action<string>(AddText), 
       message); 

Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
       new Action<string>(AddText), 
       message); 

、これを変更してくださいBeginInvokeメソッドは非同期的に呼び出され、BeginInvokeで参照されているメソッドが実行されている間、アプリケーションは実行を継続します。

はこれを読む:whether to use Invoke or BeginInvoke

+0

InvokeとBeginInvokeを入れ替えても、アプリケーションに大きな違いはありません。 – RichieACC

0

は、UIの凍結を回避するために、次のコードを使用してください。私のアプリケーションでは、私はBackgroundWorkerクラスを使用しています。コードを使用してフォーム上の何かを変更すると、実行時エラーがスローされます。

私はこれを避けるために以下のコードを使用しています。

Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate() 
{ 
    rtf_status.AppendText("Validating XML against schema...Please wait\n"); 
})); 

注カッコの間の後の部分(「{}」)フォームに何かを変更したい場合は、あなたのコードを配置する必要がある場所です。

+0

本質的に、このコードは私のものと変わりはありません。名前付きメソッドを使用している場合は、単に匿名メソッドを使用しています。 – RichieACC

関連する問題