Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Timer only executes five times?


  • Please log in to reply
11 replies to this topic

#1 CarTech

CarTech

    New Member

  • Members
  • Pip
  • 9 posts

Posted 25 October 2011 - 02:14 AM

Please be kind as I'm a mechanical engineer during the day learning both C# and the netduino as a hobby. :D

I'm using an ADXL345 accelerometer connected to the netduino via I2C. I've attached the class for the accelerometer which I got almost directly from LoveElectronics ADXL345 Library & Tutorial. This code works very nicely.

Unfortunately the sensor stick from SparkFun, which I have, doesn't have the interrupts on the ADXL345 broken out. Thus, I've resorted to polling the ADXL345 with a timer.

The problem I'm having is that the timer only executes five times. If I change the time interval (tried 8ms and 800ms), it still only runs five times. Here's the problematic code:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace Testing9DOF
{
    public class BufferFileManager
    {
        // Constructor
        public BufferFileManager()
        {
            Debug.Print("Created a new BufferFileMananger instance");
        }

        // Public methods
        public void StartDAQ()
        {
            // Start up sensor class
            ADXL345 myAccel = new ADXL345();
            myAccel.CheckConnection();
            myAccel.FullResolution = true;
            myAccel.EnableMeasurements();
            myAccel.SetDataRate(0x08);

            // Start collecting data to file
            Timer timer = new Timer(delegate(object o)
                {
                    myAccel.ReadAllAxes();
                    string data = myAccel.ScaledXAxisG + "\t" + myAccel.ScaledYAxisG + "\t" + myAccel.ScaledZAxisG;
                    Debug.Print(data);
                }, null, 0, 80);
        }
    }

    public class Program
    {         
        public static void Main()
        {
            BufferFileManager fm = new BufferFileManager();
            fm.StartDAQ();

            Thread.Sleep(Timeout.Infinite);
        }
    }
}

Now, if put everything in the Main class, it works fine:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace Testing9DOF
{
    public class Program
    {         
        public static void Main()
        {
            ADXL345 myAccel = new ADXL345();
            myAccel.CheckConnection();
            myAccel.FullResolution = true;
            myAccel.EnableMeasurements();
            myAccel.SetDataRate(0x08);

            // Start collecting data to file
            Timer timer = new Timer(delegate(object o)
            {
                myAccel.ReadAllAxes();
                string data = myAccel.ScaledXAxisG + "\t" + myAccel.ScaledYAxisG + "\t" + myAccel.ScaledZAxisG;
                Debug.Print(data);
            }, null, 0, 80);

            Thread.Sleep(Timeout.Infinite);
        }
    }
}

Not really sure what's going on. I'm guessing it's something to do with how I've attempted to put it in a second class? Any ideas?

Attached Files



#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 25 October 2011 - 02:37 AM

Hi CarTech,

When you create your Timer (named timer), it's scope is the function that it was created in (the StartDAQ function).

So after a while the garbage collector kicks in freeing up any disposable objects...and in this case it disposes your out-of-scope Timer :)

When you declared the object in your main routine, it never went out of scope (because the Main routine sleeps forever and thus never stops running). So the garbage collector never kicked in.

Solution: if you declare your Timer as a static variable at the top of your code class, then it won't go out of scope.

static Timer timer = null;

Chris

#3 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 315 posts
  • LocationIndiana, USA

Posted 25 October 2011 - 03:21 AM

Solution: if you declare your Timer as a static variable at the top of your code class, then it won't go out of scope.

static Timer timer = null;


Oh yes. The dreaded Timer scope! Chris is absolutely right. You're getting garbage collected. :)

-Valkyrie-MT

#4 georgejh

georgejh

    Advanced Member

  • Members
  • PipPipPip
  • 87 posts
  • LocationGlasgow, UK

Posted 25 October 2011 - 11:26 AM

May be better way is to use AutoResetEvent's method WaitOne(); Thus to exit the app you need to signal main thread with setting the event inside the timer delegate based on conditions you want to stop the app. If you not set it it will run forever.
More details here.

#5 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 25 October 2011 - 11:46 AM

This post is quite interesting, IMHO. It's clear that the timer instance dies after a while, but...how it works the timer callback in the MF? I mean, in the std framework, the Threading.Timer -for instance- may keep alive the hosting callback, since the registration of the handler is at the threadpool level. That may cause a memory leak. In the MF, will be the timer always safe from this viewpoint? Thank you all.
Biggest fault of Netduino? It runs by electricity.

#6 georgejh

georgejh

    Advanced Member

  • Members
  • PipPipPip
  • 87 posts
  • LocationGlasgow, UK

Posted 25 October 2011 - 05:13 PM

This post is quite interesting, IMHO.

It's clear that the timer instance dies after a while, but...how it works the timer callback in the MF?
I mean, in the std framework, the Threading.Timer -for instance- may keep alive the hosting callback, since the registration of the handler is at the threadpool level. That may cause a memory leak.

In the MF, will be the timer always safe from this viewpoint?
Thank you all.


In very first code example the main thread is closed almost immediately after it initialised and started the timer. Meanwhile timer callback manages to execute few times before been released. All thread started die when the main application thread is released. To prevent this you have to prevent main thread to be disposed, like indefinite loop (bad idea but possible), put it into sleep for indefinite time or the last, and for me best way, is to use event synchronisation. Last method allows you to be more flexible and leaves you opportunity, if you change your mind, to signal to main thread that it is now OK to continue with whatever next code might be: do something else or exit.
In case you declare the delegate inside the code, this creates "weak" delegate, which can be disposed by GC. To prevent GC to dispose the delegate (thus preventing main thread to finalise and exit) you have to declare the timer callback as static variable, as CW suggested.

Regardless of the "tricks" you may do to achieve prevention of main thread exit, I think the best way is to properly use the framework and go for event synchronisation, or any one of the other standard methods.

#7 CarTech

CarTech

    New Member

  • Members
  • Pip
  • 9 posts

Posted 25 October 2011 - 07:08 PM

Thanks for all the help!

For reference, I declared the timer as a field in the class (instead of local variable) and it works perfectly. Here's the updated code:

EDIT: fixed error in code copy paste

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace Testing9DOF
{
    public class BufferFileManager
    {
	
        // Declare timer
        private static Timer timer;
		
        // Constructor
        public BufferFileManager()
        {
            Debug.Print("Created a new BufferFileMananger instance");
        }

        // Public methods
        public void StartDAQ()
        {
            // Start up sensor class
            ADXL345 myAccel = new ADXL345();
            myAccel.CheckConnection();
            myAccel.FullResolution = true;
            myAccel.EnableMeasurements();
            myAccel.SetDataRate(0x08);

            // Start collecting data to file
            timer = new Timer(delegate(object o)
                {
                    myAccel.ReadAllAxes();
                    string data = myAccel.ScaledXAxisG + "\t" + myAccel.ScaledYAxisG + "\t" + myAccel.ScaledZAxisG;
                    Debug.Print(data);
                }, null, 0, 80);
        }
    }

    public class Program
    {         
        public static void Main()
        {
            BufferFileManager fm = new BufferFileManager();
            fm.StartDAQ();

            Thread.Sleep(Timeout.Infinite);
        }
    }
}


#8 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 26 October 2011 - 04:02 AM

In very first code example the main thread is closed almost immediately after it initialised and started the timer. Meanwhile timer callback manages to execute few times before been released. All thread started die when the main application thread is released. To prevent this you have to prevent main thread to be disposed, like indefinite loop (bad idea but possible), put it into sleep for indefinite time or the last, and for me best way, is to use event synchronisation. Last method allows you to be more flexible and leaves you opportunity, if you change your mind, to signal to main thread that it is now OK to continue with whatever next code might be: do something else or exit.
In case you declare the delegate inside the code, this creates "weak" delegate, which can be disposed by GC. To prevent GC to dispose the delegate (thus preventing main thread to finalise and exit) you have to declare the timer callback as static variable, as CW suggested.

Regardless of the "tricks" you may do to achieve prevention of main thread exit, I think the best way is to properly use the framework and go for event synchronisation, or any one of the other standard methods.

Thank you Georgi, but I'm not sure you've answering to my question.

Suppose to be in the regular framework, and the timer used is the System.Threading.Timer.
In the first example what is happening behind the scenes is:
  • the callback of the timer is passed to a free thread of the pool;
  • this background thread runs, calling periodically the handler;
What if the timer is lost?
  • None tells to the thread pool to stop running, thus freeing the resources.
  • The thread itself owns a (strong) reference to the callback, thus the instance can't be garbaged.
  • No destructor (nor dispose) is called.
Basically, you have a "zombie" thread running forever, and there's no way to stop it, unless the whole app is closed. In addition, there's a clear memory-leak because the hooking to the callback.
That's what happens in the regular framework (e.g. PC).

I wondering whether the same behavior happens in the MF as well, or the background management is much simpler/safer from this viewpoint.
In other words: using the first pattern with Netduino, may we reach to a zombie thread/memory leak?
Thank you all.
Biggest fault of Netduino? It runs by electricity.

#9 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 26 October 2011 - 06:31 AM

For reference, I declared the timer as a field in the class (instead of local variable) and it works perfectly. Here's the updated code:

Note: In the above code, there is still local timer variable declared in the Main function (it hides the class member). You'd need to replace "Timer timer = ..." with "timer = ...". In all likelihood, it is just mistake in copy & paste of your actual code.

#10 georgejh

georgejh

    Advanced Member

  • Members
  • PipPipPip
  • 87 posts
  • LocationGlasgow, UK

Posted 26 October 2011 - 06:48 AM

Thank you Georgi, but I'm not sure you've answering to my question.

Suppose to be in the regular framework, and the timer used is the System.Threading.Timer.
In the first example what is happening behind the scenes is:

  • the callback of the timer is passed to a free thread of the pool;
  • this background thread runs, calling periodically the handler;
What if the timer is lost?
  • None tells to the thread pool to stop running, thus freeing the resources.
  • The thread itself owns a (strong) reference to the callback, thus the instance can't be garbaged.
  • No destructor (nor dispose) is called.
Basically, you have a "zombie" thread running forever, and there's no way to stop it, unless the whole app is closed. In addition, there's a clear memory-leak because the hooking to the callback.
That's what happens in the regular framework (e.g. PC).

I wondering whether the same behavior happens in the MF as well, or the background management is much simpler/safer from this viewpoint.
In other words: using the first pattern with Netduino, may we reach to a zombie thread/memory leak?
Thank you all.


.NET is "managed code" world. It is designed to relieve you from worries like this. You cannot leak memory in case like the one in first code as whole resources will be disposed when the main thread close. You may leak memory only until the "parent" thread is running or you use a not managed resource(s) outside of the application, like for example with standard .NET you reserve amount of memory directly from OS API and then forget to dispose it. This will leak memory not in the app but from the environment. In case you have created not weak delegate then you will "leak" memory but still only until main thread close. That's why I was suggesting using the framework synchronisation methods instead tricks. .NETMF claims same behavior. Guarantee? Well, I presume it is exactly same, otherwise they had to redo the whole System namespace behavior to accommodate different one. Of course to be sure one have to dig into the .NETMF source, which I may do one day. Seems too many questions about behavior were risen recently, so may worth look into just to make sure it is OK :) Meanwhile I will continue to support the point to use the framework as it was designed and thus give it a chance to do its job. It's like a hammer - it is excellent tool for nailing nails but it will not stop you from misusing it over your fingers if you decide to do so :)

#11 Mario Vernari

Mario Vernari

    Advanced Member

  • Members
  • PipPipPip
  • 1768 posts
  • LocationVenezia, Italia

Posted 26 October 2011 - 07:18 AM

Georgi, the MF is running on MCUs like Netduino. It means the program (i.e. main thread) is supposed to run endlessly. BTW, I'd throw some kind of exception from within the framework when the main thread exits, because it should be an undefined condition.

So, for example, consider a class for blinking a led (e.g. 200ms period), thus embedding a timer.
Now, imagine such a code in the main thread:

static void Main()
{
  int i = 0;
  while (true)
  {
    var p = new BlinkingOutputPort(i);
    p.DoBlinking();
    i = (i+1) % 8;
    Thread.Sleep(1000);
    p.Dispose();
  }
}
Of course, that's much like pseudo-code than real.
Also consider that the programmer forgot to dispose the timer (in the IDisposable impl) embedded into the BlinkingOutputPort class.

Within the std framework, that cause a leak, plus a series of zombies.
Question: is it the same in the MF, or does exist any "advantage" keeping all that safe?

NOTE: this is much like a curiosity, because the *GOOD PRACTICE* forces me to write as I was on the regular framework. So, I'd only like to know what's behind the scene...

Cheers
Biggest fault of Netduino? It runs by electricity.

#12 georgejh

georgejh

    Advanced Member

  • Members
  • PipPipPip
  • 87 posts
  • LocationGlasgow, UK

Posted 26 October 2011 - 08:12 AM

Georgi, the MF is running on MCUs like Netduino. It means the program (i.e. main thread) is supposed to run endlessly. BTW, I'd throw some kind of exception from within the framework when the main thread exits, because it should be an undefined condition.

So, for example, consider a class for blinking a led (e.g. 200ms period), thus embedding a timer.
Now, imagine such a code in the main thread:

static void Main()
{
  int i = 0;
  while (true)
  {
    var p = new BlinkingOutputPort(i);
    p.DoBlinking();
    i = (i+1) % 8;
    Thread.Sleep(1000);
    p.Dispose();
  }
}
Of course, that's much like pseudo-code than real.
Also consider that the programmer forgot to dispose the timer (in the IDisposable impl) embedded into the BlinkingOutputPort class.

Within the std framework, that cause a leak, plus a series of zombies.
Question: is it the same in the MF, or does exist any "advantage" keeping all that safe?

NOTE: this is much like a curiosity, because the *GOOD PRACTICE* forces me to write as I was on the regular framework. So, I'd only like to know what's behind the scene...

Cheers


Hi Mario,
There is a difference in the reasons why timer dies in the first example of code in this topic and the code you asking for. Your example creates zombies because:
1. You never exit main thread. as soon as you do, it will kill the zombies.
2. Zombies are created because you are cycling on the main thread and also putting it into sleep, thus not allowing GC to do it's work. The references are kept alive because
you putting main thread to sleep before disposing them. Even after you dispose them, main thread goes to sleep very quickly again, so no GC is kicked. Try to call the GC immediately after p.Dispose() and you will see the difference. Note that zombies are created within the application's main thread context so at the moment you kill the main thread zombies will disappear. No zombies are created outside that context thus not eating system memory (Windows). In previous explanation I mentioned that the biggest danger when you use not managed system resources
which are not properly disposed. That may cause significant memory leaks and OS failure.
When you have zombies like this in standard .NET all that may happen is eventually the application stop responding and you have to kill it. Each application is given particular amount of memory and when it reach it it just hangs. In .NETMF there is no OS so this probably will cause out of memory exception and app will stop.
To simulate OS like situation you have to change the example and create new thread, whiting you create another ones. Thus main thread of your app will server the OS role, where the second thread will serve as main thread. Put your zombie creation code in this second one. Then you may try at some point to kill the second thread from first, call GC, and check the memory status - there should not be zombies left from 2nd thread.

So, the short answer to your concrete question is: yes, if you do the same thing in .NETMF it will create zombies too.
Cheers




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.