I am trying to continually run code, to execute a function as quick as it can (unless there is a specified rate.) When I had use d java before, there was a scheduler, or timer, that I had used to run code continually within a certain delay, without multi-threading. I'm looking for something similar, but no delay.
I've already tried to multi-thread, and then use a while loop, with thread.sleep to add optional delays, and then invoke a method back to then main thread. The issue with this is that it freezes my process, and causes it to be "not responding" in task manager. Although it does not interrupt the main thread, which means it runs just as intended, rendering everything, it makes the task as "not responding", which disallows me from interacting with the maximize, close buttons, resizing, etc. This is my multithreading code.
public void Init()
{
Thread thread = new Thread(Loop);
thread.Start();
}
public void Loop()
{
while (true)
{
if (InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(delegate { RenderFrame(); }));
}
if (maxFps > 0)
{
Thread.Sleep(1000 / maxFps);
}
}
}
If anyone knows how I can get the same result without freezing the process, or do it without multi-threading, please give me some pointers!!
Edit: I've decided to just go with the timer, it is slightly slower, but that's ok, I guess. One last issue with it though, is that sometimes when closing or clicking off the winform my loop ends, and it stops calling the render function. I'm using this:
var timer = new System.Threading.Timer((e) =>
{
this.BeginInvoke(new MethodInvoker(delegate { RenderFrame(); }));
}, null, 0, 1);
CodePudding user response:
You are starting a thread that is doing nothing else but bombard the UI message loop with millions of messages. That's not a good use of a thread. You need a background thread when you have work to do that is not UI-related, and in your case it seems that all the work is associated with manipulating UI components. So all the work should happen on the UI thread. In order to keep the UI responsive while the infinite loop is running, you can convert the Loop
to an async
method (async Task
or async void
), and replace the Thread.Sleep()
with await Task.Delay()
:
public void Init()
{
Loop();
}
public async void Loop()
{
while (true)
{
RenderFrame();
if (maxFps > 0)
await Task.Delay(1000 / maxFps);
else
await Task.Yield();
}
}
Instead of while (true)
you could check the condition that the main form is still open, otherwise the loop will continue after closing the form, resulting most likely in an ObjectDisposedException
.