gpt4 book ai didi

C# - 如何阻止 GUI 或事件

转载 作者:太空宇宙 更新时间:2023-11-03 14:34:43 24 4
gpt4 key购买 nike

我正在尝试使用 WPF 使用 WiiMote 创建一个非常简单的游戏 Simon 版本。我坚持的是如何使其基于转向,程序会阻塞,直到 GUI 完成显示序列。

这是我目前的代码(主要基于此处的答案:WPF - sequential animation simple example):

public partial class Window1 : Window
{

public enum SimonSquare { BLUE = 1, GREEN = 3, RED = 5, YELLOW = 7 };

List<int> _correctSequence;
int _currentLevel = 1;
Random random = new Random();
Wiimote _wiiMote;
List<int> _squaresEntered;
private IEnumerator<Action> _actions;
Rectangle blueRect;
Rectangle redRect;
Rectangle greenRect;
Rectangle yellowRect;

AutoResetEvent autoEvent;

public Window1()
{
InitializeComponent();
blueRect = new Rectangle() { Fill =
System.Windows.Media.Brushes.Blue, Name = "Blue"};
redRect = new Rectangle() { Fill =
System.Windows.Media.Brushes.Red, Name = "Red" };
greenRect = new Rectangle() { Fill =
System.Windows.Media.Brushes.Green, Name = "Green" };
yellowRect = new Rectangle() { Fill =
System.Windows.Media.Brushes.Yellow, Name = "Yellow" };

UniformGrid1.Children.Add(new Rectangle() { Fill =
System.Windows.Media.Brushes.LightGray });
UniformGrid1.Children.Add(blueRect);
UniformGrid1.Children.Add(new Rectangle() { Fill =
System.Windows.Media.Brushes.LightGray });
UniformGrid1.Children.Add(redRect);
UniformGrid1.Children.Add(new Rectangle() { Fill =
System.Windows.Media.Brushes.LightGray });
UniformGrid1.Children.Add(greenRect);
UniformGrid1.Children.Add(new Rectangle() { Fill =
System.Windows.Media.Brushes.LightGray });
UniformGrid1.Children.Add(yellowRect);
UniformGrid1.Children.Add(new Rectangle() { Fill =
System.Windows.Media.Brushes.LightGray });
//connectWiiRemote();

}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
_actions = AnimationSequence().GetEnumerator();
autoEvent = new AutoResetEvent(false);
Thread thread = new Thread(RunNextAction);
thread.Start();
autoEvent.WaitOne(); // need to block here somehow!
int x = 5;
}

IEnumerable<Action> AnimationSequence()
{
getSequence();
foreach(int square in _correctSequence)
{
if(square == (int) SimonSquare.BLUE)
yield return () => animateCell(blueRect, Colors.Blue);
else if(square == (int) SimonSquare.RED)
yield return () => animateCell(redRect, Colors.Red);
else if (square == (int)SimonSquare.GREEN)
yield return () => animateCell(greenRect, Colors.Green);
else if (square == (int)SimonSquare.YELLOW)
yield return () => animateCell(yellowRect, Colors.Yellow);
}
}

private void animateCell(Rectangle rectangle, Color fromColor)
{
this.Dispatcher.BeginInvoke(new Action(delegate
{
Color toColor = Colors.White;
ColorAnimation ani = new ColorAnimation(toColor,
new Duration(TimeSpan.FromMilliseconds(300)));
ani.AutoReverse = true;
SolidColorBrush newBrush = new SolidColorBrush(fromColor);
ani.BeginTime = TimeSpan.FromSeconds(2);
rectangle.Fill = newBrush;
ani.Completed += (s, e) => RunNextAction();
newBrush.BeginAnimation(SolidColorBrush.ColorProperty, ani);

}));
}

private void RunNextAction()
{
if (_actions.MoveNext())
_actions.Current();
else
{
autoEvent.Set();
_currentLevel++;
}
}

private void getSequence()
{
_correctSequence = new List<int>();
int[] values =
Enum.GetValues(typeof(SimonSquare)).Cast<int>().ToArray();
for (int i = 0; i < _currentLevel + 2; i++)
{
_correctSequence.Add(values[random.Next(values.Length)]);
}

}
}

但是,autoSet 的 waitOne/set 无法正常工作。它目前调用一次 RunNextAction,但随后无限期地阻塞在 waitOne 上。我做错了什么?

编辑:让我试着重新表述一下这个问题。如果我取出 Threading 和 AutoResetEvent,在 Window_Loaded 中我有:

    private void Window_Loaded(object sender, RoutedEventArgs e)
{
_actions = AnimationSequence().GetEnumerator();
RunNextAction(); // shows all of the flashing squares
// need to wait here until the flashing squares are all shown
// process player's events etc.
}

当我运行上面的代码时,它会调用一次 RunNextAction,它将继续调用自身直到显示所有方 block (它似乎在它自己的线程上),但 WindowLoaded 方法继续运行。在我调用 RunNextAction() 之后,我需要 Window_Loaded 来阻止,直到 RunNextAction 完全完成。

最佳答案

你不应该在 Dispatcher Thread 上调用 WaitOne!!

您正在 Dispatcher Thread 本身上调用 WaitOne,Dispatcher 线程是 WPF APP 的主线程,如果您阻止它,任何对 Dispatcher.BeginInvoke 或 Invoke 的调用将永远不会被调用,它将无限期地等待。

相反,更好的方法是将动画移动到另一个名为“AnimationDialog”的窗口并将其加载为模态对话框。

private void window_loaded(object sender, EventArgs e){

AnimationDialog dialog = new AnimationDialog();
dialog.Owner = this;
dialog.ShowDialog(); // this will wait here

}

在动画对话框窗口中...

private void Window_Loaded(object sender, EventArgs e){
StartAnimationThread();
// dont do any wait or block here at all...
}

// in your end of animation call "EndAnimation()"

private void EndAnimation(){
Dispatcher.BeginInvoke()((Action)delegate(){
this.DialogResult = true;
// this will stop this dialog and
// and execute the parent window's
// code where showdialog was called...
}
)
}

关于C# - 如何阻止 GUI 或事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1512425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com