私は 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 の新しい非同期機能は、たとえ問題が解決されたとしても、利用できません。