Main Site Documentation

Timers vs Threads


#1

Hi,

I’m looking for some clarity on understanding the difference between using threads with while loops, and timers.

I haven’t tried my current program with threads yet but I am successfully using two timers, that I have tried to synchronize as I believe that a timer will be blocked if the previous timer hasn’t completed it’s task. Is this correct?

For simplicity’s sake lets say that the first timer polls some inputs and the second writes the results to the SD card. I know how long it takes to poll the inputs so I make sure that timer is longer and the second timer fires before the first one fires again. So timer 1 fires every 130ms, it takes 90ms max to poll the inputs so the second timer to write the results is offset by 115ms. It only takes a few ms to write the details to the SD card so I know that is done before the timer to poll the inputs is fired again.

So am I understanding timers and using them correctly? The main reason that I ask is because I’ve been recording the times that the first timer fires and I found a weird pattern where periodically the first timer doesn’t fire. It can be seen in the attached chart of the results. It also appears to be unreliable in it’s timing, only hitting 130ms around 70% of the time.

So what about using threads? Is it possible that I can poll the inputs in a while loop in one thread, and write the results to the SD card in another? If so, will the two threads actually execute simultaneously?

Many thanks in advance for any help.


#2

You didn’t specify, what timers you use. In any case, NETMF is not a real-time system, so if you really want to synchronize something, you should use Auto-or-ManualResetEvents.

You can, of course, use Threads (and Thread.Sleep() functions in a while cycle), but this will desync quickly - due to Garbage Collector, other threads, ethernet functions and other things. Thread.Timer class is somewhat better in this case, because it does not accumulate error: it tries to execute at specified intervals. For example, if you set this timer to execute every 1000ms, and for some reason, it executes after 1100ms, the next time it will try to execute after 900ms. This is what you effectively see in the graph.


#3

I’m using System.Threading.Timer, is that what you mean by what timer I’m using? I don’t really understand what Auto-or-ManualResetEvents so I will go and read up on them.

Thank you for this explanation. That would certainly explain the variation around 130ms for the most part, but what about the sequential looking timer events that are around twice the specified interval? Any ideas?


#4

What are you really wanting to do?

It sounds like you are wanting to poll inputs at a fixed rate and write that to an sd.

I would approach this in a different way. Put the polling in a timer and que the results and let another thread @ lower priority unque and write to the sd. This way the timer will run pretty much on schedule.


#5

Hi,
recently I read an interesting blog about synchronzing threads in .NET

“Why AutoResetEvent is slow and how to synchronize threads in .NET”

Sometimes it seems to be the best to work with boolean variables (first example in the blog).
Regards
Roland


#6

About threats and prior’s you have a good and simple explanation on this old blog post:

But there are some other thing to keep in mind, threads in netmf are round robin’s and you need to understand what time quantum is used for each thread and then calculate what speed is still possible. Timers use allot less recourses as threads so when possible use timers (if you are at the border of limited powers, and in netmf this border is easily reached)


#7

Thank you for the link Roland, I’ll take a read. I also just found an article on threading and synchronization;

http://programming4.us/enterprise/1492.aspx

That’s basically what I’m doing yes. Polling at a fixed rate and writing the results to SD.

I’m afraid though that I don’t know what you mean by queue and unqueue the results. Apologies, I’m still learning!

Many thanks.


#8

[/quote]That’s basically what I’m doing yes. Polling at a fixed rate and writing the results to SD.[/quote]

If you are able to write data before the next polling you should leave all code in the timer event. If you have async data or data burst then you need to start buffering and handling in separate thread’s.


#9

@ wolfbuddy -
queuing can be done by using the Queue Class
http://msdn.microsoft.com/en-us/library/ff689202.aspx

@ David@ Emrol
do you know something aboud the speed of the NETMF Queue Class compared to a “selfmade” circular buffer?


#10

@ RoSchmi - Nope :slight_smile: but what do you mean with a “selfmade circular buffer”


#11

I use a byte array, a readpointer and a writepointer and have to be very careful about the contents of these 3 things. When I come to the last index of the array, I continue with writing at array[0].


#12

Here is the logger code in a separate class that has been working for me good at a 5 second rate:


        public static void startwritelog(GTM.GHIElectronics.SDCard sdCard)
        {
            
            if (!logon)
            {
                logon = true;
                Task.Run(() =>
                {
                    while (logon)
                    {
                        while (!sdCard.IsCardMounted)
                        {
                            sdCard.MountSDCard();
                            Thread.Sleep(500);
                        }
                        Thread.Sleep(5000);

                        string rootDirectory = "\\SD";
                        string path = rootDirectory + @ "\log.csv";

                        if (!File.Exists(path))
                        {
                            // Create a file to write to. 
                            StreamWriter sw = new StreamWriter(path);
                            sw.WriteLine("Counter,Pump1Off,Pump2Off,Pump3Off,Pump4Off,Ana1,Ana2,Ana3,Ana4,DateTime");
                            sw.Flush();
                            sw.Close();
                            Thread.Sleep(250);
                        }

                        StreamWriter logFile = new StreamWriter(path, true);
                        Thread.Sleep(250);
                        logFile.WriteLine(logger());  //grab the data to be stored and write it to sd card
                        logFile.Flush();
                        logFile.Close();
                        
                    }
                });
            }
            }

The less time you have a file open the less likely a problem with the file occurring. You also need to wait a bit for the sd card to be read/writeable though.


#13

RoSchmi - I just read the article on AutoResetEvent that you mentioned in your post. Very interesting findings. Any ideas why it is so slow?


#14

@ RoSchmi - thanks for the link.

[quote=“David@ Emrol”]If you are able to write data before the next polling you should leave all code in the timer event. If you have async data or data burst then you need to start buffering and handling in separate thread’s.
[/quote]

I am actually writing the data at the end of the polling timer and thats working fine, but I need to be able to poll some inputs at one rate, say 50ms, and the rest at a slower rate of around 500-1000ms. I also have a display to show data that can’t be updated at a high rate (350ms is OK), or it becomes unreadable, so I’m trying to work out how I’m going to do all these things successfully at different rates.


#15

@ jasdev Sorry, no idea.
@ logictechs Thank you for the code.

@ wolfbuddy

Why not use several timer with different intervals?


#16

I’m going to write a version of my program that uses timers with different intervals and one that uses threads with loops to see which gives the best results. I’ve done tons of reading and I can’t decide which is more suitable, probably due to a lack of experience! This way I’ll get the experience and learn some more stuff along the way. :smiley:

I’ll report back when I have something working.


#17

I think you should first answer yourself a question: “do things MUST be strictly synchronized?”. If the answer is “Yes”, then Auto/ManualResetEvents is the way to go (as you are talking about 1000ms, I wouldn’t worry about the performance). If it is “No”, then you can safely go with timers and threads (threads are somewhat easier for me).


#18

@ wolfbuddy - In NETMF, timers and threads are almost the same.
Timer threads are injected to the round robin scheduler queue only when the timer period elapsed.
Therefore, a timer takes no resources until next tick.
A thread polling DateTime to measure elapse time do take resources.

Another factor is to be considered: the NETMF thread time slice is 20ms. This means that the minimum practical timer period is more than 20ms (main thread time slice + timer thread execution time if less than 20ms).
A smaller period can only be reached by one thread polling the system time.


#19

For me, I would use timers to collect the data and a thread that gets resumed when needed to write the data to the SD. But I don’t know all of your requirements. That’s the fun part of doing all of this and you can experiment and change things as you go.


#20

The thread scheduler 20ms time slice does not allow very good synchronization.
AFAIK, the only reliable methode is to keep code in one thread (no timers) and to use only static variables to keep out of GC.