如何实现时间延迟



我已经编程三周了,所以我试着构建一个内存游戏。除了延迟,一切都很好。我尝试了许多不同的选项,但不知何故,延迟是在Button_Click事件结束时。

如果我单击第一个按钮,它会更改内容,但当我单击第二个按钮时按钮,无论哪个if语句触发,第二张卡都不会显示。代码工作良好,直到事件结束,然后发生3秒的延迟

我想实现的是,你可以在短时间内看到第二张卡在两张牌都被翻回来或消失之前。

附言-如果我在"延迟"后添加MessageBox,似乎可以工作但这不是目标,所以有没有像等待同步之类的东西,或者我错过了什么?

代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
int index = ContainderGrid.Children.IndexOf(button);
mCounterSecondPic++;
button.Content = new BitmapImage(new Uri(mImgPath[mPairs[index]]));//change content
mPic[mCounterSecondPic-1] = mPairs[index];
button.IsEnabled = false;
if (mPic[0] == mPic[1] & mCounterSecondPic == 2)
{
mCounterSecondPic = 0;
new System.Threading.ManualResetEvent(false).WaitOne(3000); //wait for 3sec
ContainderGrid.Children.RemoveAt(mPairs.IndexOf(mPic[0]));
mPairs.RemoveAt(mPairs.IndexOf(mPic[0]));
ContainderGrid.Children.RemoveAt(mPairs.IndexOf(mPic[0]));
mPairs.RemoveAt(mPairs.IndexOf(mPic[0]));
}
if (mCounterSecondPic == 2 & mPic[0] != mPic[1])
{
mCounterSecondPic = 0;
new System.Threading.ManualResetEvent(false).WaitOne(3000);//wait for3 sec
ContainderGrid.Children.Cast<Button>().ToList().ForEach(resetbuttons =>
{
resetbuttons.IsEnabled = true;
resetbuttons.Content = new BitmapImage(new Uri(mCardBack));
});

}

ps:如果我在"延迟"之前添加一个messageBox,似乎会起作用但那不是高尔夫球场,是不是有点像等待同步或我错过了什么?

MessageBox.Show("x");
new System.Threading.ManualResetEvent(false).WaitOne(3000);

让我们简化代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
button.Content = "START" //change content
new System.Threading.ManualResetEvent(false).WaitOne(3000); //wait for 3sec
button.Content = "FINISH" //change content
}

这样你就有了下面的时间线:

  1. 设置内容(但不查看/感觉(
  2. 你开始等待3秒钟
  3. 你等了3秒钟
  4. 设置内容(但不查看/感觉(
  5. 退出Button_Click方法
  6. 您实际上看到/感觉到内容发生了变化

正如您所看到的,内容更改(在第1项和第4项(并没有立即发生,而是发生在很久之后;这是由于UI线程在执行Button_Click方法时被阻塞,因此无法刷新图形
为了实现您想要的目标,您有两种选择:

  • 使用async/await
private async void Button_Click(object sender, RoutedEventArgs e)
{
button.Content = "START" //change content
await Task.Delay(3000); //wait for 3sec asynchronously
button.Content = "FINISH" //change content
}
  • 使用Dispatcher
private void Button_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Dispatcher.Invoke(() => button.Content = "START");
System.Threading.Thread.Sleep(3000);
Dispatcher.Invoke(() => button.Content = "FINISH");
}).Start();
}

最新更新