Main Site Documentation

Info on threading


#1

I’m looking for information regarding threading in netmf. I am using the FEZMini robot kit. I’m assuming this information is available on tinyclr or elsewhere, but so far I’ve had no luck finding it. Any assistance where to look is appreciated.

Ralf


#2

Threading on NETMF works just like threading on .NET on a PC so basically just search fro “threading C#” and you will find what you need.

Or ask specific questions and we will try to help better


#3

That’s a start. I keep seeing “quasi” in relationship to threading on the hardware and I was wondering what that was implying: is this “true” threading or are there nuances with threading on the hardware I’m not aware of. That is, are there any “gotcha’s” I should be on the look out for that I might overlook coming from a PC developer background?

I was able to code a module that operates the LED on the FEZMini board (On, Off, Toggle and Blink) via threading. The idea is to have a single module that allows me to control the LED with simple statements like LED.Blink() or LED.On(), allowing other modules to ignore the details of making that happen and without having to wait. I wanted to ensure I wasn’t missing anything in my implementation.

BTW, I’m sure I’m not the only one to do this. Are there other code samples of this somewhere I can review to compare notes with what I did? It would be useful to see what more experienced developers are doing in this regard.

I did notice that there doesn’t seem to be support for a parameterized thread start object in NETMF. Am I missing something there?

Thanx,

Ralf


#4

Threading on FEZ are very well supported and complete.

It is a bad practice to start stop threads frequently, on a PC or on FEZ, you can use timers instead. See this http://www.fezzer.com/project/35/led/


#5

Here’s another example of a blinking led with a timer :

using System;
using System.Threading;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace PandaTimer
{
    public class Program
    {
        public static Timer timer = null;
        public static OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);

        public static void Main()
        {
            BlinkLed(250, 10);  // Blink led with a 250ms pulse, 10 times
            Thread.Sleep(Timeout.Infinite);
        }


        static void BlinkLed(int freq, int nbre)
        {
            led.Write(false);   // Start with a known "off" state
            try
            {
                timer.Dispose();
            }
            catch { }    // No timer yet or timer already disposed
            finally
            {
                timer = new Timer(new TimerCallback(CallBack), new State(nbre), freq, freq);   // Activate timer
            }
        }

        static void CallBack(Object stateObject)
        {
            State state = (State)stateObject;   // New instance of the "State" class
            state.Count++;           // Increment count
            led.Write(!led.Read());  // Invert led state
            if (state.Count > state.Iter)  // Stop when Iteration reached
            {
                timer.Dispose();
                led.Write(false);   // End with "off" state
            }
        }
    }

    public class State
   {
      public int Count = 0;   
      public int Iter = 0;    

      public State(int nb)    
      {
          Iter = nb << 1;   
      }
   }
}

Pretty self explanatory, I think.

A small note, however : if you call BlinkLed before a preceding call has finished running, the new one will “replace” the old one, hence the try-catch block, which tries to dispose an already existing timer.
You can try to add this after the first call to see what I mean :


Thread.Sleep(1000);  // 1000 < 250*10, so the following call will start before the current one has finished
BlinkLed(250, 10);  

This is needed behaviour for what I do. It can of course be done differently if you want to “queue” the calls, for example.


#6

That’s what I was looking for. Thanx.

I’m used to working with server and desktop centric code so I have the luxury of not having to worry much about memory consumption or making code especially efficient in my day to day. This is a new twist for me. I can already see this is going to assist me in my regular programming.

I’ll be honest and admit the timer approach never occurred to me. I was using the PWM sample in the beginner guide as a starting point and going from there. The timer approach seems more straight forward. I’m going to take a fresh look at this.

Does NETMF have a thread pool?

Thanx again,

Ralf


#7

@ Ralf - same for me - .NET developer by day, NETMF developer by night.

I also see how this can help make think more efficiently for my server/desktop apps.

In my project I started with threads, but have switched to timers. As soon as my motor driver shows up, I’ll know how efficient or inefficient this approach will be.

Once I get my project somewhat stable, I’ll put up my code.


#8

Based on empirical evidence, it seems Timer runs on a single thread (looks like native code implementation), so no other timer callback will run while you are inside a timer callback. So if your blocking or sleeping in a callback, no other timer callback will fire. Therefore, Timer may not be the best option in many cases. So manual threads may be required depending on needs.


#9

It looks like the NETMF threading model does not support the Monitor Wait/Pulse methods. Do I see that correctly?

Thanx,

Ralf


#10

That is correct. They had to chop all none critical things to stay small. Naturally, everything is criticle when you need it. You can, however, create pulse/wait with careful use of Monitor and a Reset Event and then codify that in your own Monitor wrapping .net monitor. I will post a snippet.


#11

I created a snippet here of Monitor2 with Pulse/Wait. Let me know if see and error. tia
http://www.fezzer.com/project/106/monitor2/


#12

Thanx, that was helpful. I adapted the code for my purposes. I changed the “Monitor2” class to a static class rather than sealed. Also, I added a try/finally block inside the Pulse() method.

Again, Thanx,

Ralf


#13

I have never seen a event.Set() throw an exception, but try/finally probably adds symmetry from other methods. I am not sure about what the static implementation. You would be sharing a global monitor. I probably not understanding something. Maybe you could post that code here? tia


#14

I went static mostly as a matter of style. I prefer this sort of syntax:


bool okToContinue = false;
object syncObject = new object();

//[....]

lock(syncObject)
    while(okToContinue == false)
        Monitor2.Wait(syncObject);

//[....]

lock(syncObject)
{
    okToContinue = true;
    Monitor2.Pulse(syncObject);
}


This is 99% of my rationale. However, there are performance considerations using static versus instance classes. At least that’s my understanding.

First, by making Monitor2 an instance class, there are three objects created on the heap: The Monitor2 instance and the two internal objects: sync and wait. If a 2nd, independent Monitor2 instance is created, there are now 6 objects on the heap. And so on. This takes up memory space and the CLR has to keep track of these objects for GC purposes.

Also, static method calls are slightly faster than instance method calls. Each time an instance method is called, a null reference check is required and the instance members (sync and wait) have to be located on the heap. Again, that is how I understand it. I’m not sure what the differences are in this regard in the context of the TinyCLR which evidently has a different way of doing these sorts of things than the full CLR does.

As a practical matter, I don’t generally worry about that in my normal coding environment - the performance savings are trivial in that context. And besides, proper design is far more important for good performance than these sorts of things in most situations. This is undoubtedly true in the TinyCLR world as well.

But since resources are at a premium in the microprocessor world, I see no harm in squeezing out what I can. It’s a good exercise in any event and I concede my understand may be flawed and my logic wrong as a result.

Here is my implementation. As you can see, I’ve deleted the Enter() and Exit() methods since they are redundant to the Monitor class. Oh, and I reversed the Enter/Exit calls in the Pulse(object) method from the original. I’m not sure if that was correct on my part.



using System;
using System.Threading;
using Microsoft.SPOT;

namespace MF.Threading
{
    public class Program
    {
        #region test code
        private static object s_Sync = new object();
        private static bool s_okToContinue;

        static void Main(string[] args)
        {
            new Thread
            (
                () =>
                {
                    Debug.Print("Thread Start");
                    lock (s_Sync)
                    {
                        while (!s_okToContinue)
                        {
                            Monitor2.Wait(s_Sync);
                        }
                    }
                    Debug.Print("Thread Pulse");
                }
            ).Start();

            Thread.Sleep(100);
            Debug.Print("Wait");
            lock (s_Sync)
            {
                s_okToContinue = true;
                Monitor2.Pulse(s_Sync);
            }
            Debug.Print("Zzzzz");
            Thread.Sleep(Timeout.Infinite);
        }
        #endregion
    }

    /// <summary>
    /// A Monitor implementation that adds Wait and Pulse
    /// </summary>
    public static class Monitor2
    {
        //private static readonly object _sync;
        private static readonly AutoResetEvent s_wait = new AutoResetEvent(false);

        /// <summary>
        /// Wait for pulse.
        /// </summary>
        /// <param name="sync">The object to sync against.</param>
        public static bool Wait(object sync)
        {
            if (sync == null)
            {
                throw new ArgumentNullException("sync");
            }

            return Wait(sync, -1, false);
        }

        //Wait for a specified time. -1 = infinity
        private static bool Wait(object sync, int millisecondsTimeout, bool exitContext)
        {
            Monitor.Exit(sync); // Exit lock and wait for Pulse.
            try
            {
                // If we timeout waiting for Pulse, return false.
                return s_wait.WaitOne(millisecondsTimeout, exitContext);
            }
            finally
            {
                // Always re-enter the lock after wait.
                Monitor.Enter(sync);
            }
        }

        /// <summary>
        /// Release a thread waiting on Wait
        /// </summary>
        /// <param name="sync">The object to sync against.</param>
        public static void Pulse(object sync)
        {
            if (sync == null)
            {
                throw new ArgumentNullException("sync");
            }

            Monitor.Exit(sync);
            try
            {
                s_wait.Set(); // Pulse 1 waiting.
            }
            finally
            {
                // Always re-enter the lock after set so caller retains the lock.
                Monitor.Enter(sync);
            }
        }
    }
}


Thanx,

Ralf


#15

@ Ralf, your logic is a quite wrong with regards to the usage of AutoResetEvent. You can’t have one AutoResetEvent for multiple locks, otherwise you will be forcing all though threads to be effectively serialized (i.e. they all act as one thread) since they will all end up waiting on the same AutoResetEvent, (even though the locking is on different lock objects),and only one thread will be ‘Pulsed’ at a time.

Also, asides from this, for the pulse method, you should only pulse if you have access to the lock. Original order of Enter, Set, Exit is correct, NOT Exit, Set, Enter, you will get odd / unsafe threading behavior with it this way. Be best to keep behavior in line with Monitor.Pulse behavior.

From MSDN:

Only the current owner of the lock can signal a waiting object using Pulse.

The thread that currently owns the lock on the specified object invokes this method to signal the next thread in line for the lock. Upon receiving the pulse, the waiting thread is moved to the ready queue. When the thread that invoked Pulse releases the lock, the next thread in the ready queue (which is not necessarily the thread that was pulsed) acquires the lock.

http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse(VS.71).aspx


#16

@ William - Can I recommend you make one addition to your Monitor2 class on Fezzer? Can you make it implement IDisposable so in the event of an exception being thrown within it will release the lock?

For example:


Monitor2 _monitor = new Monitor2(new object());
...
using(_monitor2)
{
      _monitor2.Enter(); // get the lock to start with

      // business logic here.
      for(int i=0; i< 10; i++)
      {
             if(i == 6)
             {
                      // something bad happened.
                      throw new Exception();
             }
      }


} // IDispose will auto exit the lock and prevent deadlocks.

#17

@ Ralf. Couple issues. I started out in that direction, but realized the wall I quickly hit.

  1. You are breaking apart the monitor and using lock on outside and then having Monitor2 do some work inside. ?? This defeats the purpose of codifying the implementation details in one place and abstracting those details. Much harder to reason about and easy to make a mistake, and there are probably other issues with that I would have to look harder at.
  2. Your sharing a single reset event for every lock you take, even if you lock on a different object and breaks the lock contract. This will only work with 1 lock as in your code. However, if your locking on different objects as is normal then you have a problem.

If you need the locks, you need the locks and would not worry about the few bytes. You will take up way more bytes by not using the shared logic and duplicating the steps all over the program. Which is what we want a class for.


#18

“Can I recommend you make one addition to your Monitor2 class on Fezzer? Can you make it implement IDisposable so in the event of an exception being thrown within it will release the lock”

@ Ross. You could, but I left it out for this same reason. You would be changing the contract of what IDisposable is and be confusing (am I exiting or disposing here ??). Dispose is supposed to close the object and release all resources. So you are changing Dispose to really just mean Exit(). That may make sense to some, or be broken for others. This is situation for try/finally and how manual use of the normal Monitor is used.


var mon = new Monitor2();
mon.Enter();
try
{
    // do stuff in lock context.
}
finally
{
    mon.Exit();
} 

It may be a few more braces, but is more familar to how people expect to use Monitor. The “lock” keyword is actually sugar and expands to this try/finally under the covers.


#19

Yeah fair point with the meaning of IDisposable. Yep some nice syntax sugar it is too, I have a lot of my code the way you have just showed, I just find it ugly…but it is ‘cleaner’ compared to IDisposable from a conceptual POV. Maybe you could add that snippet below as sample usage on Fezzer. I think people without too much threading experience may get deadlocks if they are not aware of using it as it should be below.


#20

I noticed they took out Usage samples, unless I am just not seeing it.
I have been adding Static test methods to the Class as sample/test. However, I wonder about this strategy in general. As cutter/paster’s may not want the extra method in the clean class or want to remove them all the time. Maybe we can decide on what strategy to use for usage samples. On the pro side, it would mean you only have copy one class and have everything in a single unit.