2015-05-25 48 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关于如何执行此操作。

相关问题