Remi Beaulieu Remi Beaulieu -4 years ago 271
C# Question

c# UWP How to schedule something to run after current Dispatcher.ProcessEvents()? Is it even possible?

Im trying my hand at creating a very simple "game engine" to play around in universal platform and Win2D.

I want to create a "main game loop" that can be started and stopped.

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;
}


If I call StartGameLoop() right in some page's "Loaded" event, everything works like a charm.

private void Page_Loaded(object sender, RoutedEventArgs e)
{
StartGameLoop();//all good
}


But if I do call StartGameLoop() inside a button's "click" event I get a catastrophic failure exception stating "Nested calls to ProcessEvents method is not allowed.", witch can actually make some sense.

private void Button_Click(object sender, RoutedEventArgs e)
{
StartGameLoop();//will cause exception on Dispatcher.ProcessEvents()
}


So I'm searching for a way to be sure the game loop starts after any potentially running ProcessEvents() call when I click on those UI buttons.. and I'm fresh out of ideas :)

Thanks for any help.

Answer Source

Try await Task.Yield();

This tells the dispatcher to process anything after the yield when it's done processing. This is not guaranteed... the dispatcher decides what's priority, but give it a try and see if it's what you need.

https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.yield(v=vs.110).aspx

Just an example, try this:

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();
    }
});

Note the async () => {...} in the RunAsync method.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download