我正在尝试创建一个非常简单的“游戏引擎”,以便在通用平台和Win2D中玩游戏。
我想创建一个可以启动和停止的“主游戏循环”。
public async void StartGameLoop()
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
GameLoopStopSignal = false;
while (!GameLoopStopSignal)
{
//something like good old DoEvents()?
CoreApplication.MainView.CoreWindow.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);
//Game Tick
Tick();
}
});
}
public void StopGameLoop()
{
GameLoopStopSignal = true;
}
如果我在某个页面的“已加载”事件中调用StartGameLoop(),那么一切都像魅力一样。
private void Page_Loaded(object sender, RoutedEventArgs e)
{
StartGameLoop();//all good
}
但是如果我在按钮的“click”事件中调用StartGameLoop(),我会遇到一个灾难性的失败异常,说明“不允许对ProcessEvents方法进行嵌套调用。”,女巫实际上可以有所帮助。
private void Button_Click(object sender, RoutedEventArgs e)
{
StartGameLoop();//will cause exception on Dispatcher.ProcessEvents()
}
因此,当我点击那些UI按钮时,我正在寻找一种方法来确保游戏循环在任何可能正在运行的ProcessEvents()调用之后启动...我想出了新的想法:)
感谢您的帮助。
答案 0 :(得分:1)
尝试await Task.Yield();
这告诉调度员在完成处理后处理后的任何事情。这不能得到保证......调度员会决定优先级,但请尝试一下,看看它是否符合您的要求。
https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.yield(v=vs.110).aspx
举个例子,试试这个:
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, async () =>
{
GameLoopStopSignal = false;
while (!GameLoopStopSignal)
{
//something like good old DoEvents()?
CoreApplication.MainView.CoreWindow.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessAllIfPresent);
await Task.Yield();
//Game Tick
Tick();
}
});
请注意async () => {...}
方法中的RunAsync
。
答案 1 :(得分:0)
最后我恢复使用Task.Run()(因此在线程池上运行主循环)而不是在CoreWindow.Dispatcher上运行(在主UI线程中);似乎绕过了我遇到的所有问题。不确定它最终会回来咬我但手指交叉。
public void StartGameLoop()
{
Task.Run(() =>
{
GameLoopStopSignal = false;
clock.Start();
while (!GameLoopStopSignal)
{
Tick();
}
clock.Stop();
});
}