# [.net] C# and GUI threads

## Recommended Posts

nullsquared    126
I'm confused about how to do a proper C# game loop. Once you create a Form, all the events are called automatically from a separate thread, as far as I can tell. So, where does my game loop go? If I put it in the main thread, then I might have issues when handling GUI events while my game loop is processing stuff. What is Application.DoEvents() used for considering it all happens automatically? (Just straight up C# and .NET stuff, no XNA or anything)

##### Share on other sites
Kaze    948
try a timer object and put your game code in the ontick event

##### Share on other sites
nullsquared    126
Is there any other way of doing it?

ragnarsun    133

##### Share on other sites
nullsquared    126
Quote:
 Original post by ragnarsunLook at Tom Miller Loop

I've seen that. I'm just trying to find a cleaner, completely .NET based approach. I mean, come on, C# and .NET are so amazing that you can't do a proper game loop without invoking native win32 functions?

##### Share on other sites
Fiddler    860
Quote:
Original post by nullsquared
Quote:
 Original post by ragnarsunLook at Tom Miller Loop

I've seen that. I'm just trying to find a cleaner, completely .NET based approach. I mean, come on, C# and .NET are so amazing that you can't do a proper game loop without invoking native win32 functions?

Not really. All other approaches allocate memory, use up too much CPU time or are wildly inaccurate from a timing-perspective.

The only other approach is to spawn a different thread and do your work on that. Do note that you won't be able to access the main Form directly (you'll have to use BeginInvoke and the like), but this approach works and is "clean".

On the other hand, Tom Miller's loop is simpler. Don't let the p/invoke scare you off, I've been using this approach successfully for years on all all major operating systems (Windows, Linux, OSX, porting the loop is straightforward).

##### Share on other sites
nullsquared    126
Quote:
 Original post by FiddlerOn the other hand, Tom Miller's loop is simpler. Don't let the p/invoke scare you off, I've been using this approach successfully for years on all all major operating systems (Windows, Linux, OSX, porting the loop is straightforward).

Okay, guess I'll just go with that then. It's not scary, I just thought that .NET would have something just as good built in [grin].

And out of curiousity, what do you mean you've been using this approach on several OS's? I thought the whole PeekMessage() idea would only work on Windows?

##### Share on other sites
I've done this. Don't use the Timer component. Instead use a Thread timer.

See usage for a .Net render surface here and create your own OnPaint event.
private System.Threading.Timer frameTimer;private System.Threading.TimerCallback frameTimerCallback;private int frameNumber = 0;  //what number frame are we currently on? 0..60private const int frameRate = 60;public RenderSurface()  //constructor{  InitializeComponent();  this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  this.SetStyle(ControlStyles.ResizeRedraw, true);  this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);}public void Begin(){  this.frameTimerCallback = new System.Threading.TimerCallback(frameCallBack);  this.frameTimer = new System.Threading.Timer(this.frameTimerCallback);  this.frameTimer.Change(0, 1000 / frameRate);   //start immediatly. }private void frameCallBack(object obj){  this.frameNumber++;  if (frameNumber >= frameRate)    this.frameNumber = 0;  this.Invalidate();  //calls Paint which triggers a render}

##### Share on other sites
Fiddler    860
Quote:
Original post by nullsquared
Quote:
 Original post by FiddlerOn the other hand, Tom Miller's loop is simpler. Don't let the p/invoke scare you off, I've been using this approach successfully for years on all all major operating systems (Windows, Linux, OSX, porting the loop is straightforward).

Okay, guess I'll just go with that then. It's not scary, I just thought that .NET would have something just as good built in [grin].

And out of curiousity, what do you mean you've been using this approach on several OS's? I thought the whole PeekMessage() idea would only work on Windows?

Yes, but every OS provides a way to query for pending messages. For example, on Linux (and everything else that has an X server), you can use XPending. The implementation is slightly more complicated, because you need to gain access to the Form's private display connection but it's not too bad. For comparison: Windows implementation vs Linux implementation (you only need lines 35-36, 81-86 and 111-114 of the Linux one, the rest have to do with OpenGL initialization and are not relevant here).

Usage looks like this:
Application.Idle += (sender, e) =>{    while (control.IsIdle)    {        // update and render    }};

##### Share on other sites
nullsquared    126
Quote:
Original post by Fiddler
Quote:
Original post by nullsquared
Quote:
 Original post by FiddlerOn the other hand, Tom Miller's loop is simpler. Don't let the p/invoke scare you off, I've been using this approach successfully for years on all all major operating systems (Windows, Linux, OSX, porting the loop is straightforward).

Okay, guess I'll just go with that then. It's not scary, I just thought that .NET would have something just as good built in [grin].

And out of curiousity, what do you mean you've been using this approach on several OS's? I thought the whole PeekMessage() idea would only work on Windows?

Yes, but every OS provides a way to query for pending messages. For example, on Linux (and everything else that has an X server), you can use XPending. The implementation is slightly more complicated, because you need to gain access to the Form's private display connection but it's not too bad. For comparison: Windows implementation vs Linux implementation (you only need lines 35-36, 81-86 and 111-114 of the Linux one, the rest have to do with OpenGL initialization and are not relevant here).

Usage looks like this:
*** Source Snippet Removed ***

Very cool, thanks for the information!