lid6j86's picture

Fast Loops

I'm trying to make a fast loop class that will constantly refresh the screen when the system is Idle. here is what i'm using right now:

#using System.Runtime.InteropServices;
#using System.Windows.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace GenericGameLibrary
{
 
   [StructLaout (LayoutKind.Sequential)]
   public struct Message
   {
      public IntPtr hWnd;
      public Int32 msg;
      public IntPtr wParam;
      public IntPtr lParam;
      public uint time;
      public System.Drawing.Point p;
   }
 
    /// <summary>
    /// Fastloop takes a function and runs it continuously
    /// </summary>
    public class FastLoop
    {
       [System.Security.SuppressUnmanagedCodeSecurity]
       [DllImport("User32.dll", CharSet = CharSet.Auto)]
       public static extern bool PeekMessage(
          out Message msg,
          IntPtr hWnd,
          uint messageFilterMin,
          uint messageFilterMax,
          uint flags);
 
 
        public delegate void LoopCallback(); //Container variable for function that will be looped continuously
 
        LoopCallback _callback; //stores sent function for future use
 
        //Constructor, takes in 1 argument (looping function)
        public FastLoop(LoopCallback callback)
        {
            _callback = callback; //set local _callback to function that is sent in args
            Application.Idle += new EventHandler(OnApplicationEnterIdle); //listens for system to be idle and runs the event handler OnApplicationEnterIdle
        }
 
        //Event handler for when the system is idle
        void OnApplicationEnterIdle(object sender, EventArgs e)
        {
            while (IsAppStillIdle()) //determines if the app is still idle, and if it is it continues to run
            {
                _callback();  //runs the function that was sent as an arg
            }
        }
 
        private bool IsAppStillIdle() //function that looks for system idle  
        {
            Message msg;
            return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0); //if there is a message in queue, it returns true, so ! is needed to say that it is not idle if there is a message (send false)
        }
    }

This obviously is pretty specific to Windows, and can only work on windows because its calling windows APIs. My question is this: Is there a more cross-platform friendly version of this? What is the fastest method of checking if the processor is Idle while keeping it cross-platform code?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
lid6j86's picture

(by the way, there should not be 2 # symbols before the first two 'using' statements

the Fiddler's picture

If you are using OpenTK.GLControl, you can use the "IsIdle" property:

GLControl glControl = new GLControl();
 
Application.Idle += (sender, e) =>
{
    while (glControl.IsIdle)
    {
        // do something
    }
};

If you are using OpenTK.GameWindow, you can call GameWindow.Run() without parameters to run without a frame limit.

lid6j86's picture

so this basically goes to the platform its on and checks for idle from any use?

I would still have to put up top using System.Windows.Forms to access Application.Idle.... is that a Windows specific reference?

the Fiddler's picture

Exactly.

Mono implements System.Windows.Forms on Linux and Mac OS X, but the result is not exactly optimal (it works, but it doesn't look native).

flopoloco's picture

I use OpenTK's GameWindow all of the time, so I have not look into it in depth. A bare-bone fast loop class isn't simply like this?

using System;
 
namespace FastLoop
{
	class Program
	{
		public static void Main(string[] args)
		{
			bool isRunning = true;
 
			while (isRunning)
			{
				Console.WriteLine(DateTime.Now.Millisecond.ToString() +
				                  " " +
				                  DateTime.Now.Second.ToString());
			}
		}
	}
}

It keeps updating constantly, no matter what the status of the Form/Window is. No need to mess with the Windows event handling and add extra overhead. Do you agree?

lid6j86's picture

I don't think that would be the best, because it wastes cycles. The method I posted above and, I'm hoping, the OpenTK method look to see if other instructions want to run, and allow them if they are queued. That way your program doesn't hog up more resources than it needs to.

On your PrecisionTimer, I don't think that it is really precise enough when getting into accurate graphics manipulation. From what I've been reading, there are far more accurate and precise ways to get the time. The method I'm using calls Kernel32 within windows to get the cycle and frequency, from which you can get a precise time that runs independent of the processor speed. Once again from what I've read, this is what allows all games or programs to run at the same speed regardless of the computer speed.

If you've ever played a really old DOS game without it being ported recently, for instance, you'd notice that it is unplayable because the updates/game runs too fast.

Once again, I'm not an expert. I'm brand new into this forray. I've spent the last 2-3 days pulling my hair out over trying to read XNA, OpenTK, OpenGL, and DirectX literature, then converting it to classes and libraries that I want to use as a basis for my games.

I'm having a hard time finding literature that explains every option for a function or class, and why they are used. Most things I find just explain what to use in one specific situation, then you are left wondeirng what it all means and why it was used in that situation.

I still have mostly dealth with 2d, and haven't gotten much into 3d, so I still have no idea how to map out large areas, manipulate the camera and viewing area, etc... I can only assume that it will involve a lot of math and multidimensional arrays (and perhaps matricies, which I still haven't looked at yet)

flopoloco's picture

If you need some ideas you can have a look at MonoGame which is XNA+OpenTK (even use mono game instead of writing your own game loop).

https://github.com/mono/MonoGame/blob/develop/MonoGame.Framework/Game.cs

Inertia's picture

@lid6j86 from what you're saying I suggest: do not worry about efficiency at all. If you are really trying for efficiency, you cannot use .Net, because it's applications will inevitably run slower than unmanaged code.

It's a good idea to read up on stuff like garbage collection and design your code right away to avoid the pitfalls. But avoid reading too many tech papers and books on engine design and all that buzzwords. It's easy to get stuck in analysis-paralysis. Usually people have at least 2 different opinions on things and none is clearly superior.

Don't take this as offense, but one cannot plan something one has no experience with. Don't try for perfect. Perfection doesn't exist. The best one can do is flawless, or to be more precise "without noticable flaws". You can aim for that, once you are somewhere between reached "functional" and "feature complete".

Just don't be afraid to start coding and experiment. .Net rules everything else in this regard. You spend far less time debugging things, so it's not that much of a loss if you decide the approach is bad and delete a class and start over. Just do remember the separation of concerns when designing you code and you will be fine. If -at some point- you decide that some module is horribly illformed and must be replaced, then so be it. No battle plan ever survived 1st contact and the same is (at least in my experience) true for programming.
The exception to that statement may be a complete rewrite of a program you wrote before, because then you do have experience and can plan it ahead (assuming you really do not add anything new and just rewrite it in a more elegant way). But I don't know for sure, never decided that a complete rewrite would be the best course of action.