Threading and timers inside an emulator - c#

I'm developing a Chip-8 emulator in C#, I have completed partially almost every aspect but there is something I'm still wondering about speed control of the emulator.
What I'm doing now is assuming that I get 60 frames per second, I use a timer that fires 1/60 seconds in the following manner (pseudocode):
timer_ticked()
{
for(int i = 0; i < Settings.CyclesPerFrame; i++)
{
EmulateCycle();
}
if (IsDrawFlagSet)
{
DrawGraphics();
}
}
I'm using a high resolution timer called microtimer http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer , I believe that the timer doesn't wait for timer_ticked to finish to fire the next cycle (fon instance, creating a new thread) and I'm having an issue with threads and the form since trying to paint to a window with GDI (using the control.GetGraphics() method) seems to be threadsafe, but trying to create an SDLDotNet approach (just an example) doesnt.
Which approach do you think is best to control the speed of an emulator without getting into timer thread insanity?
PS: You can find the source code of the emulator in GitHub: https://github.com/AlFranco/C8POC
Thank you!

If you tick method is being called again before it's done, the problem isn't with your timer. It's because the processing is taking longer than that 16.6 ms. Getting a better timer isn't going to solve your problem.
That said, you can prevent reentrancy in a couple of ways.
You could just disable the timer when you enter the callback, and re-enable it when you're done. That'll prevent multiple invocations:
timer_ticked()
{
timer.Enabled = false;
// do stuff here
timer.Enabled = true;
}
Note that this doesn't give you a perfect 16.6 ms tick frequency. Rather, the next tick will occur 16.6 ms (approximately) after you enable the timer. Your real period is 16.6 ms plus however long it takes to do the processing.
The only time this would fail is if the timer_ticked method wasn't called before the next tick happened.
If you want to guarantee that you can't get concurrent ticks, you can use a System.Threading.Timer and set it up as a one-shot (no periodic signaling). For example:
Timer myTimer = new Timer(timer_tick, null, 16, -1);
The -1 in the last parameter tells it not to be a periodic timer. It'll fire once and stop.
Then, in your timer tick:
timer_tick()
{
// do stuff
// restart the timer
myTimer.Change(16, -1);
}
Edit
You can't easily tell the timer not to issue a tick if the handler is still processing the previous tick. You can, however, prevent the timer tick handler from doing anything on that subsequent tick. You simply use a Monitor:
private object timerLock = new object();
timer_ticked()
{
if (!Monitor.TryEnter(timerLock))
return;
try
{
// do stuff here
}
finally
{
Monitor.Exit(timerLock);
}
}
The problem with such a solution is that if your timer is set of 16 ms and the handler takes 17 ms, then your effective update rate will be once every 32 ms, because the second tick is essentially ignored. You're better off with the one-shot timer deal.
Another possibility is to use a Stopwatch to time how long your handler takes, and subtract that from the next delay period:
timer_ticked()
{
var sw = Stopwatch.StartNew();
// do stuff
timer.Change(16-sw.ElapsedMilliseconds, -1);
}
But it's not quite that simple. If it takes longer than 16 ms for the handler to do its thing, you'll end up with a negative delay. So you'll want:
var delayTime = Math.Max(0, 16 - sw.ElapsedMilliseconds);
timer.Change(delayTime, -1);
But again, if your handler regularly takes longer than the timer delay, then this isn't going to help you. You'll either have to reduce your timer frequency (i.e. make a longer delay) or optimize your processing code.

Related

From AS3 to C# a simple elapsed Timer

I need to set up a simple elapsed Timer in C# (MonoBehavior) that calls a method when complete, but can also be cancelled before finishing. If cancelled or stopped, it automatically resets its interval. I don't need anything fancy like threading.
Reading over the documentation on C# Timers https://msdn.microsoft.com/en-us/library/System.Timers.Timer%28v=vs.110%29.aspxstill a bit confused. For instance, when you set mytimer.Enabled=false does it also reset the timer back to 0? Perhaps I should be looking at Coroutines instead?(this is for Unity)
In AS3 I would do something like this
private var _delayTimer:Timer;
//create a Timer object that runs once for 1 second
_delayTimer = new Timer(1000,1);
//add handler
_delayTimer.addEventListener(TimerEvent.COMPLETE, onDelay);
//start timer
_delayTimer.start();
private function onDelay(e:TimerEvent):void{
trace('delay finished!);
}
//some other method to interrupt-stop and reset the delay timer
private function foo():void{
_delayTimer.reset();
}
By using System.Timers.Timer, you are using multi-threading - it's quite likely this is not what you want.
Instead, you probably want System.Windows.Forms.Timer - this will post the timer event back on the UI thread (if you're using Windows Forms, of course).
You can use Start and Stop the way you want, because there's actually no ticking clock - it just registers a callback from Windows in the future, basically.
Relevant piece of documentation from MSDN:
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.

Firing a sound with a timer in a backgroundworker, wp7 phone app

I am hitting a wall and have come here hoping you guys can help me out with the following:
I am designing a wp7 app where I am having sounds fire off periodically (every 700 ms). I want these sounds to play on another thread than the UI thread. Thus, I cannot use a dispatch timer because the UI thread will be heavily used in the meantime while these sounds fire.
In looking at this problem, I made a backgroundworker with a Thread.Sleep(700) command. This works, but as one may expect it can take longer than 700 ms to fire off a sound. So sometimes I hear delays.
So I turn to you guys -- How can I get as close to a firing of a sound every 700 ms in a backgroundworker or another thread? Is a Timer a wise idea?
Here is some code to better illustrate:
private void RunBackgroundWorker()
{
backgroundWorker = new BackgroundWorker ();
backgroundWorker.WorkerSupportsCancellation = true;
backgroundWorker.DoWork += new DoWorkEventHandler(StartSounds);
backgroundWorker.RunWorkerAsync();
}
public void StartSounds(object sender, EventArgs e)
{
for (currentsoundchoice = 0; currentsoundchoice <= max; currentsoundchoice ++)
{
if (backgroundWorker.CancellationPending == true)
{
backgroundWorker.CancelAsync();
currentsoundchoice = max + 1; //just to ensure it stops.
}
else
{
Time_Tick();
if (max == 12)
currentsoundchoice = -1; //repeats the loop when it reaches max.
}
}
}
void Time_Tick()
{
Thread.Sleep(700);
FrameworkDispatcher.Update();
switch (sounds)
case 0: //code
break;
// ETC, So forth.......
}
I heard that using a Timer is also a good way to go about this, but is it possible to run a timer in a backgroundworker, and if so, how would it be structured? More importantly, would it allow me to get as close to the 700 ms firing time I desire without any audible delays?
Thank you.
BackgroundWorker is the wrong choice here. It is designed to allow you to perform expensive work on a background thread and then synchronize the results back to the UI. You do not need any synchronization. Moreover, you need the work to occur at a regular interval - not as a one-off task.
A Timer would be much more suited. It would allow you to run your logic every 700ms and to remove the nasty Thread.Sleep() call you have in your current code. The Timer will use a background thread just like BackgroundWorker does.
Note, however, that it can only guarantee that it won't run before 700ms has elapsed. If you're absolutely hammering the device, for example, it may struggle to run your code on a regular interval and you may notice lag.

Perform a event certain so many times every so many seconds

I am currently working on a c# project where I need to perform a task so many times every so many seconds.
For example, write to the console 5 times every 1 second. How could I go about doing this.
Thanks for any help you can provide.
You can use a Timer and bind and event to the Timer.Elapsed event.
using System.Timers;
Sample code:
Timer timer = new Timer();
timer.Elapsed += (sender, eventArgs) =>
{
for (int i = 0; i < 5; i++)
{
Console.Write(i);
}
};
Is this an console application, or do you run this on another thread?
For short stuff like this, use a timer. There are two main ones to choose from:
System.Threading.Timer
And:
System.Windows.Forms.Timer
The former uses the ThreadPool, the latter uses UI events. They both expose the ability to specify and interval and either a callback method or event to attach to in order to put custom code.
For longer periods of inactivity, look into scheduling either with the Windows scheduler (the OS one) or a scheduling framework such as Quartz.NET.
Do note that the accuracy of the timers vary, but not really within margins that humans can detect :-)
Also note that the callback of the threaded timer will return on an arbitrary ThreadPool thread, so you could effectively end up "multi-threading" the code without realising it.
There is also System.Timers.Timer, it exposes an event. An article about the different timers available can be found here.
I don't think it will affect you, but it's still worth knowing - windows is not a real-time OS; if you ask for something to be done every X milliseconds, it won't be exact, as for how much it will be out depends on a variety of things.
You could create a thread to do it. Especially useful if you want to do a lot of processing! Here's an example of a thread doing work every 1s (1000ms):
public void Start()
{
running = true;
thread = new Thread(new ParameterizedThreadStart(ThreadFunction));
thread.Start();
}
public virtual void ThreadFunction(object o)
{
var insert = false;
while (running)
{
//Do work
Thread.Sleep(1000);
}
}
try this
While (true)
{
for (int i=0; i<5; i++)
{
console ("Hello");
}
//this will pause for 1 sec (1000msec)
Thread.sleep(1000);
}

How to make async pause in C#?

I have a program written in C# (Visual Studio), that works on a tray.
I want it to do one action every 10 minutes.
I have following code now:
while(true)
{
Thread.Sleep(10000);
// my stuff
}
But it doesn't work. It freezes a program.
You should use the timer object and not create a while loop.
System.Timers.Timer _timer = new System.Timers.Timer();
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
//30 seconds
_timer.Interval = 30000;
_timer.Start();
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//do your logic
}
Thread.Sleep makes the calling thead Sleep for an X ammount of time. If this thread is the frontend thread (the one responsible for handling messages), it will indeed freeze the application since any message for handling events or repainting wont be handeled untill the Thread wakes up again and gets a chance of handling the messages.
What you should do is schedule this logic every 10 seconds.
Drop a timer on your form and specify it to run each 10 seconds. Within the Tick event, call your custom action.
Thread.Sleep "stops" the current thread. if you only have one thread, everything is paused.
What do you want to achieve ?
Perhaps you need a second thread, or perhaps the better solution a timer which triggers a action every 10 minutes
s. Task.StartNew() or ThreadPool

contextswitchdeadlock

Whilst debugging my program in VS 2008 I have come across the following error:
The CLR has been unable to transition from COM context 0x34fc1a0 to COM context 0x34fc258 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this
It appears to be deadlocking even though the code only contains a simple C# timer: See Snippet Below:
private void RequestWork()
{
// The timer will be re-intialised if there are still no wating jobs in the database
StopTimer();
// assign all the threads some work
InitialiseTimer();
}
/// <summary>
/// Initialise a timer with a timer interval configured from app.config. Enable the timer and
/// register an appropriate event handler
/// </summary>
private void InitialiseTimer()
{
if (m_Timer == null)
{
// look up the default backoff time from the config
string backOffInt = ConfigurationSettings.AppSettings["BackOffInterval"];
int backoffInterval = 1000;
m_Timer = new System.Timers.Timer();
// set the timer interval to 5 seconds
m_Timer.Interval = backoffInterval;
m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
}
m_Timer.Enabled = true;
}
private void StopTimer()
{
if (m_Timer != null)
{
m_Timer.Enabled = false;
}
}
void m_Timer_Elapsed(object p_Sender, ElapsedEventArgs p_E)
{
RequestWork();
}
As far as I know the timer should run, elapse and then initialise again, I can see no local reason for a deadlock.
I am aware of how to turn this error msg off but feel that this is not a solution, instead it is masking the problem.
You can turn this off if you think you've definitely not got a deadlock situation:
Debug->Exceptions->Managed Debug Assistants menu in Visual Studio and uncheck the ContextSwitchDeadlock
This is an infinite loop. You need to let your application pump some messages at least once every 60 seconds to prevent this exception to happen.
Try calling System.Threading.Thread.CurrentThread.Join(10) once in a while. There are other calls you can do that let the messages pump.
It seems that you are adding a new event handler each time you call InitialiseTimer. That way m_Timer_Elapsed will be called as many times as it has been added.
You should add the event handler just one time.
If your application hangs or not reponse even after you uncheck the box against contextswitchdeadlock. Put the following line before call of method or for loop.
In C#
System.Windows.Forms.Application.DoEvents();
and VB.NET / VB / ASP.NET
DoEvents()
Couple thoughts/questions:
1) The code snippet looks like your interval is every 1 second (not 5 as mentioned in the comments).
2) The big question is what is RequestWork() doing?
Without knowing what RequestWork() is doing, we can't really comment on why you are seeing a ContextSwitchDeadlock.
Somethings to think about with respect to this method
a) how long does it take?
b) is it accessing GUI elements?
Some MSDN comments on Elapsed:
If you use the Timer with a user
interface element, such as a form or
control, assign the form or control
that contains the Timer to the
SynchronizingObject property, so that
the event is marshaled to the user
interface thread.
-and-
The Elapsed event is raised on a
ThreadPool thread. If processing of
the Elapsed event lasts longer than
Interval, the event might be raised
again on another ThreadPool thread.
Thus, the event handler should be
reentrant.
I'm thinking since you have a 1 second timer, you might want to look into what happens in RequestWork and see how long its taking.

Categories