2

私は WPF4 プロジェクトで MVVMLight を使用しており、ビューのボタンにバインドされている ApplyCommand と UndoCommand を設定しています。すべての標準的なことは、何度も行われました。ユーザーがボタンをクリックすると、WCF サービス メソッドが呼び出され、ローカル変数が更新されます。UndoCommandCanExecute メソッドは、このローカル変数を使用して、UndoCommand を実行できるかどうかを判断します。

WCF サービス呼び出しを同期的に行うと、これは正常に機能します。ただし、非同期呼び出しを使用すると、CanExecute メソッドが起動されないため、元に戻すボタンが正しく有効化/無効化されません。

以下は、両方のコマンドによって呼び出されるビュー モデルのプライベート メソッドの簡略化されたバージョンです。実際のコードでは、サービス呼び出しで使用されるパラメーターが渡されます。

  private void CallServiceMethod() {
    IsBusy = true;
    Task t = new Task(() => {
      Thread.Sleep(2000); // would really call a WCF service
      SetUndoMessage();
      IsBusy = false;
    });
    t.Start();
  }

前述のとおり、WCF サービス呼び出しは、単純化のために Thread.Sleep への呼び出しに置き換えられました。SetUndoMessage() メソッドは、UndoCommandCanExecute メソッドが使用するローカル変数を設定します。IsBusy は、ビューの Telerik ビジー インジケーターにバインドされた bool であるため、ユーザーは何かが起こっていることを確認できます。

これを実行すると、ウィンドウのどこかをクリックするまで、元に戻すボタンが正しく有効または無効になりません。Debug.WriteLine ステートメントをあちこちに追加したところ、タスクのコールバックが終了したときに UndoCommandCanExecute メソッドが呼び出されていないことがわかりました。

タスク コールバックの最後に次の 2 行を追加しようとしましたが、役に立ちませんでした...

    CommandManager.InvalidateRequerySuggested();
    UndoCommand.RaiseCanExecuteChanged();

Thread.Sleep を削除すると問題なく動作しますが、問題は遅延のようです。このメソッドは、タスクが終了する前に終了しているため、UndoCommandCanExecute メソッドは起動していません。RaiseCanExecuteChanged メソッドまたは CommandManager を呼び出したときに起動しない理由がわかりません。

スレッドを開始した直後に t.Wait() を追加しようとしましたが、サービス呼び出しが終了するまでビジー インジケーターが表示されず、目的全体が無効になりました。

これを修正する方法はありますか?非同期呼び出しを維持したいと考えています。これにより、この大規模なアプリケーション全体で標準となっているビジー インジケーターを使用できるようになり、ユーザーに何かが起こっているというフィードバックが得られます。

ちなみに、私は C# 4 の使用に行き詰まっているため、C# 5 の新しい非同期機能は、たとえ問題が解決されたとしても、利用できません。

4

1 に答える 1