2015-05-25 106 views
1

我正在編寫一個WPF'Reversi'遊戲,其中玩家在8x8網格中按下一塊圖塊來放置一塊石頭。如何在不導致InvalidOperationException的情況下延遲ICommand執行?

這是一個棋子在瓦片上的命令:

private class Click : ICommand 
    { 
     private readonly SquareViewModel squareViewModel; 

     public ClickCommand(SquareViewModel squareViewModel) 
     { 
      this.squareViewModel = squareViewModel; 

      squareViewModel.Square.IsValidMove.PropertyChanged += (sender, args) => 
      { 
       if (CanExecuteChanged != null) 
       { 
    /*->*/   CanExecuteChanged(this, new EventArgs()); 
       } 
      }; 
     } 

     public event EventHandler CanExecuteChanged; 

     public bool CanExecute(object parameter) 
     { 
      return squareViewModel.Square.IsValidMove.Value; 
     } 

     public void Execute(object parameter) 
     { 
      squareViewModel.Square.PlaceStone(); 
     } 
    } 

我已經設定的AI是放在一塊石頭時,它的播放器2的依次是:

void CurrentPlayer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
      Player player = ((ICell<Player>)(sender)).Value; 
      if (player != null && player.Equals(Player.TWO)) 
      { 
       Vector2D nextMove = ai.FindBestMove(boardViewModel.Game); 
       rowDataContexts[nextMove.Y].SquareDataContexts[nextMove.X].SquareViewModel.Click.Execute(null); 
      } 
     } 
    } 

這工作完全正常。不過,我希望愛好者在2秒後立即行動,而不是立即行動。

我試圖實現這樣的延遲:

void CurrentPlayer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
    { 
      Player player = ((ICell<Player>)(sender)).Value; 
      if (player != null && player.Equals(Player.TWO)) 
      { 
       Vector2D nextMove = ai.FindBestMove(boardViewModel.Game); 
       Task.Delay(2000).ContinueWith(_ => 
        { 
         rowDataContexts[nextMove.Y].SquareDataContexts[nextMove.X].SquareViewModel.Click.Execute(true); 
        }); 
      } 
    } 

但是這導致的InvalidOperationExceptionClickCommand在與CanExecuteChanged(this, new EventArgs())(我第一個代碼示例中放一個箭頭,相關線路)線路。這發生在2秒後(只要Task.Delay繼續)。

我該如何解決這個問題?

回答

2

該異常是由在非UI線程上執行該命令引起的,因爲現在它是由線程池中的線程執行的任務的一部分。

使其工作切換到任務或ViewModel中的UI線程。

根據設置,如果您使用的是正確的ViewModel,則可以選擇在ViewModel基類中的UI線程上引發PropertyChanged,因爲大部分時間響應該事件的主要原因是更新UI。 請參閱https://stackoverflow.com/a/24882812/563088關於如何執行此操作。

相關問題