2017-04-13 13 views
2

タスクと非同期/待機中のキーワードと混同されています。私はあなたが非同期とブロックコードを混ぜるべきではないことを理解します。または、少なくともそれらを混合する私の解釈は、次のとおりです。await/asyncタスクが待機していません

非同期メソッドからブロッキングAPIを呼び出さないでください。だからここに私の問題です。

私はメソッドを待つことを試みており、それに従ってUIを更新しています。問題は、非同期のmethod()呼び出しを待つ唯一の方法がwithinとasync method()からのものであることです。

はここに例を示します

private RelayCommand<Options> _executeCommand; 

public RelayCommand<Options> ExecuteCommand 
{ 
    get 
    {     
     return _executeCommand ?? (_executeCommand = new RelayCommand<Options>(async (options) => 
     { 
      Completed = false;      

      var cancellationTokenSource = new CancellationTokenSource(); 

      await RunValidation(options, cancellationTokenSource.Token); 

      Completed = true; 

     })); 
    } 
} 

このコードは正しくメソッドを実行してお待ちしています。問題は私が帰ったときです。何らかの理由でCompleteフラグを設定するとき、このフラグに依存するボタンはトグルされません。待っているコードにコメントすると、ボタンが正しく切り替わります。だから私は、UIスレッド上で戻っていなかったと仮定ので、私が代わりにこのコードを使用してみました:ここ

private RelayCommand<Options> _executeCommand; 

public RelayCommand<Options> ExecuteCommand 
{ 
    get 
    {     
     return _executeCommand ?? (_executeCommand = new RelayCommand<Options>(async (options) => 
     { 
      Completed = false;      

      var cancellationTokenSource = new CancellationTokenSource();                 

      var context = TaskScheduler.FromCurrentSynchronizationContext(); 

      await RunValidation(options, cancellationTokenSource.Token).ContinueWith(t => Completed = true, context); 

      //Completed = true; 

     })); 
    } 
} 

はRunValidation()メソッドです:

private async Task RunValidation(Options options, CancellationToken token) 
{    
    await _someService.SomAsyncMethod(options, token)); 
} 

あなたが気付いた場合、ExecuteCommandは非同期を持っていますコマンドに渡される(オプション)パラメータの前にキーワードを入力します。非同期キーワードを削除すると、RunValidation()メソッドの呼び出しを変更する必要があります。私はまだそれを待つ必要があるので、これは私がやったことです:

private RelayCommand<Options> _executeCommand; 

public RelayCommand<Options> ExecuteCommand 
{ 
    get 
    {     
     return _executeCommand ?? (_executeCommand = new RelayCommand<Options>((options) => 
     { 
      Completed = false;      

      var context = TaskScheduler.FromCurrentSynchronizationContext(); 

      var cancellationTokenSource = new CancellationTokenSource(); 

      Task.Run(async() => await RunValidation(options, cancellationTokenSource.Token)); 

      Completed = true; 

     })); 
    } 
} 

このコードの問題は、それが待っていないということです。だから私は迷っている。

誰でも私のためにこれにいくつかの光を当ててください。私はこれに2プラスの日を費やして、私はまだここにいる。ここで

おかげで、 ティム

は、コマンドボタンにバインドされています。

private readonly Independent<bool> _completed = new Independent<bool>(true); 

public bool Completed 
{ 
    get { return _completed; } 
    set { _completed.Value = value; } 
} 

private ICommand _doneCommand; 

public ICommand DoneCommand 
{ 
    get 
    { 
     return _doneCommand ?? (_doneCommand = MakeCommand.When(() => Completed).Do(() => 
     { 
      DoSomething(); 
     })); 
    } 
} 

private ICommand _cancelCommand; 

public ICommand CancelCommand 
{ 
    get 
    { 
     return _cancelCommand ?? 
       (_cancelCommand = MakeCommand.When(() => !Completed).Do(() => DoSomthingElse())); 
    } 
} 

私はマイケル・ペリーからUpdateControlsライブラリからMakeCommandオブジェクトを使用しています。これらには、Completeプロパティが変更されたときにCanExecuteChangeイベントを発生させる依存追跡が含まれています。

+2

最初のコードブロックは正しいです。ボタンはCompletedフラグにどのようにバインドされていますか?それは観察可能ですか? – Jason

+0

あなたの問題は通知が失われていることが原因で、あなたの通知が必要なライブラリを使用しているので、UpdateControlsライブラリで問題を提起することをお勧めします。 –

+0

私は狂っていないし、物事の外観から、私はものを正しくやっている? – user953710

答えて

0

最初のコードは正しいです。ほとんどの場合、Completedプロパティの実装が正しくない可能性があります。ビューモデルオブジェクトはINotifyPropertyChangedを実装する必要があります。この権利を行う最も簡単な方法は、機能を提供する基本クラスを使用することです。 ReactiveUIはいつも使っているナゲットパッケージです。使用法このプロパティが変更されたときに通知をUIに上げていることを確認します

public class MyObject : ReactiveObject { 

    private bool _Completed; 
    public bool Completed { 
     get => _Completed; 
     set => this.RaiseAndSetIfChanged(ref _Completed, value); 
    } 

} 

のと同じくらい簡単です。

あなたはそれはあなたがReactiveUI.Fodyを使用することができ、その後、あなたのコードはそう問題は、実際には、サードパーティのライブラリだった

public class MyObject : ReactiveObject { 

    [Reactive] 
    public bool Completed { get; set;} 

} 
0

に削減するより魔法のようにしたい場合。私はそれを使って2つのボタンの依存関係を追跡していました。だから、完全なフラグが変更されたとき、それを行うコードを書かずに、両方のボタンのCanExecuteChangeイベントを発生させました。残念ながら、非同期/待機の呼び出しを導入した後は動作を停止しました。私は2つのMakeCommandsをRelayCommandsに置き換えて、自分自身でイベントを発生させ、すべてが機能しました。

ご回答いただきありがとうございます。

ティム

関連する問題