2011-01-25 15 views
7

階層化されたアーキテクチャを持つアプリケーションがあるとします。ビューでは、MVCまたはMVVMを使用します。モデルはドメインとして扱われ、ビジネスロジックの優れた部分を持っています。ビジネス/モデルクラスから進行状況の更新を送信する方法は?

ここでモデルに時間がかかるメソッドがあるとします。複雑な計算や、例えばオブジェクトの各項目に対して行わなければならない処理。

UIでは、進行状況バーと、計算の現在のステップを表示するテキスト(たとえば、すべてのプロセス履歴を含むリストボックス)を表示したいとします。

どうすればよいですか?どのようにプロセスの進捗状況の情報をモデルから送信するか、コントローラまたはViewModelを接続して進捗状況を更新する方法を教えてください。

答えて

5

多くの場合、次のように実装します。実行に時間がかかるビジネスレイヤープロセスは、特定の「マイルストーン」に当たることを示すために、頻繁にイベントを発生させます。イベントを通ってどのマイルストーンを伝えるか、どれくらいのマイルストーンを決めますか?時間のかかるプロセスが単純ループである場合は、ループ内のアイテムの10%ごとに同じイベントを何度も繰り返すことができます。異なるフェーズのプロセスである場合は、各フェーズが完了するたびに異なるイベントを発生させることができます。

あなたのプレゼンテーション層は、それらのイベントにサブスクライブし、その結果として動作し、プログレスバーやテキストなどを更新します。ビジネス層は、プレゼンテーション層にまで上に行くかもしれないものとは独立したまま

  1. :ので

    このメカニズムは良いです。

  2. 双方向通信のために拡張が容易です。プレゼンテーション層(または他のサブスクライバ)がキャンセルフラグを返すことができるように、イベントを簡単に変更することができます。これにより、長期実行プロセスをキャンセルする必要があることがビジネス層に分かります。
  3. 同期処理と非同期処理のいずれかを許可します。つまり、コールをブロックする(プレゼンテーションとビジネスレイヤが同じスレッドを共有する)ブロッキングでも、ブロッキングでもないコール(つまり、ビジネスレイヤでバックグラウンドワーカースレッドが使用される)にも使用できます。後者の場合はSystem.ComponentModel.BackgroundWorkerクラスを使用できますが、複数のタイプのイベントを発生させたい場合はそれほど優れていません。

これが役に立ちます。

+0

非常に完全な答えをありがとう。イベントの見方は、ビジネスレイヤーにはない非常に技術的な問題でした。しかし結局、プロセスがどのように進行しているかに関する情報を送信する方法がなければなりません。 – Gimly

+0

@Gimly:どうぞよろしくお願いいたします。私はイベントが "アクティブな"オブジェクトを実装するビジネス層で便利だと思います。あなたの質問のシナリオは良い例です。 – CesarGon

0

オブザーバーパターン(http://en.wikipedia.org/wiki/Observer_pattern)を探検する必要があります。それはデスクトップアプリケーションのためのかなり一般的なアプローチです。 Webにとってもう少し複雑です。また、Comet [http://en.wikipedia.org/wiki/Comet_(programming)]を調べて、Webでどのように処理されているかを調べることもできます。

+0

間のデータバインディングに、更新されます。しかし、私はそれが正しいとは思わない、それはビジネスに技術的なものがあることを意味するので、私は少し間違って感じる。 – Gimly

0

私は同様の場合に以下のアプローチをとった。このビューには、時間がかかるアクションがあり、定期的に進捗状況を表示したいと考えています。長時間実行されているアクションは、別のクラスのWorkerにプッシュダウンされます。いくつかのユーザアクションがTestViewModelのDoSomethingへの呼び出しを開始します。

TestView.xaml

... 
<!-- Progress bar --> 
<ProgressBar Visibility="Visible" Height="10" Value="{Binding SomeValue}"/> 
... 

TestViewModel。CSはBaseViewModel、BaseViewModelだけINotifyPropertyChangedの

... 
private void DoSomething(){ 
    Worker worker = new Worker(); 
    worker.ProgressChanged += new EventHandler<WorkerEventArgs>(OnProgressChanged); 
    worker.Start(); 
} 

private void OnProgressChanged(object sender, WorkerEventArgs args){ 
    SomeValue = args.Progress; 
} 

private const String SomeValuePropertyName = "SomeValue"; 
private double someValue; 
public double SomeValue 
{ 
    get 
    { 
     return someValue; 
    } 
    set 
    { 
     if (someValue == value) 
     { 
      return; 
     } 
     someValue = value; 
     NotifyPropertyChanged(SomeValuePropertyName); 
    } 
} 
... 

Worker.csに

... 
public event EventHandler<WorkerEventArgs> ProgressChanged; 
public void Start(){ 
    //This will take a long time. Periodically call NotifyProgress 
} 

private void NotifyProgress() 
{ 
    if (ProgressChanged != null) 
    { 
     double progress = ...; //calculate progress 
     ProgressChanged(this, new WorkerEventArgs(progress)); 
    } 
} 
... 

WorkerEventArgs.cs

public class WorkerEventArgs : EventArgs 
{ 
    public double Progress { get; private set; } 

    public WorkerEventArgs(double progress) 
    { 
     Progress = progress; 
    } 
} 
2

を実装して、私はSystem.ComponentModel名前空間で提供さBackgroundWorkerクラスを見て推薦を拡張します。

背景労働者はあなたが別のスレッドで、あなたの集中的な操作を実行するために必要な方法を提供し、進行状況に関するステータス更新を受け取ります(ReportProgressProgressChangedRunWorkerCompleted経由)。

私は実際には、スケジュールされたタスクを実行する目的で、ウェブ環境でBackgroundWorkerを使用して実験してきました。私はこれまでにコードプレックスで行った作業を発表することにしました。私のコードの精神があなたの状況に役立つと感じます。 'Web Scheduled Task Framework' codeplex project

プロジェクトをダウンロードする場合は、ScheduledTaskRunnerクラスでBackgroundWorkerクラスをどのように使用しているかがわかります。私の実装では、進捗状況イベントをワーカーに付けることはできませんが、非常に簡単です。また、私の現在の実装では、一定の間隔でタスクを実行することに焦点を当てていますが、それを「オンデマンド」処理キューのほうに変更することはあまり難しくありません。私はそれを今考えている機能として追加することもできます:)

あなたが上記の私のコードのアプローチに従ったと仮定すると、あなたのコントローラにアクションを作成して、 「タスク」(またはあなたが興味を持っている特定のタスク)を選択し、その情報を何らかの種類のActionResultとして報告します。いくつかのjavascriptを設定して、指定した間隔でアクションをポーリングしてください。

幸運にも、私のコードについてご質問がありましたらお知らせください。

1

他のコメントに基づいて、ビジネスレイヤーをできるだけきれいに保つようにしています。

次にモデルビューViewModelにアプローチが合うことがあります。http://en.wikipedia.org/wiki/Model_View_ViewModel

をcalcualtionが行われているとして、あなたは進歩がなされたことをイベントを投げます。

これらのイベントはViewModelで捕捉され、進行状況が更新されます。

ビューは、それがネットではかなり一般的ですので、私は、当然のオブザーバーパターンについて考えによるビューモデルとビュー(Observerパターン)

関連する問題