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

Proper way to multithread on Netduino


  • Please log in to reply
5 replies to this topic

#1 Anshul

Anshul

    Advanced Member

  • Members
  • PipPipPip
  • 50 posts

Posted 08 July 2013 - 05:40 AM

I have seen a few ways to do multithreading, and after reading a few posts on here I'm still unsure of what is the "correct" way to do multithreading. Specifically, I'm concerned with threads that will be monitoring inputs by constantly reading them and updating some output (like a brightness meter). 

 

Way 1 is to have a thread and have a while (true) loop in there with a Thread.Sleep(1) and the polling code. I have noticed that if I don't put a Thread.Sleep(1) in there, the debugger stops responding and there's no way to get Visual Studio to attach to the debugger without erasing the current program. (My guess is that the main CLR thread doesn't get enough time to both interrupt VS while it's waiting for the CLR debugger and receive the attach message from VS. But if we put Thread.Sleep(1) in the polling thread, the main CLR thread would get a lot more time to run while the polling thread is sleeping and is able to interrupt VS and also receive the attach message (or debugging symbols).)

 

Way 2 is from http://forums.netdui...ring-whileloop/. One of the responses was as follows:

 

 

[color=rgb(164,164,164);font-family:helvetica, arial, sans-serif;]Posted [/color]21 February 2013 - 09:18 AM

Hi Ties,

The way that threads work in NETMF is that each thread gets up to ~10ms to execute before the thread scheduler pulls the execution to another thread. In order to make sure that interrupts are fired in sequence, NETMF queues and timestamps them...and then fires them off in order.

In multi-threaded and interrupt-driven apps, we generally avoid loops or any action that ties up the processor for long periods of time. But if you'd like to run long loops for threads, you'll probably want to create a thread and launch it there. With the newer versions of .NET MF, you can even use anonymous methods to launch code on another thread "in-line" in your code.

You can also create background threads for each of your tasks and then have them wait on an AutoResetEvent waithandle. Then when your interrupt gets fired, just Set the waithandle and your background thread will come to life. This also helps keep thread count down and prevent unintentional re-entry.

There are a massive number of powertools available in the C# language and NETMF, so there should be one that's great for the application at hand. We're happy to help guide the selection process.

Chris

 

My question is what does "background threads" mean in the context of this message? I cannot find the class BackgroundThread in NETMF, so was wondering if setting the priority of the thread to BelowNormal or Lowest makes it a background thread? Would a background thread also require a Thread.Sleep(1) in its while loop? (Side question: How do you create a thread "in-line", as mentioned in the quote above?)

 

Those are the two ways that I'm aware of. I'd love to hear more suggestions, and also thoughts about which threading methods are suited for what applications (polling an input, blinking an LED, etc.)



#2 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 08 July 2013 - 09:00 AM

Hi!

 

There's no special class for "Background threads", they are the same as any System.Threading.Thread. In the post you refer to, the term is used to denote a Thread who's purpose is to process data produced by an interrupt service routine (ISR) in order to avoid lenghty operations in the ISR itself.

 

The AutoResetEvent is used to have the "background thread" wait for a signal before going to work. It's a good example of the common producer/consumer pattern where the ISR is the producer and the background thread is the consumer.

 

You can use a System.Connections.Queue object for the ISR to quickly tuck work items away (using the Enqueue method) to be processed by the background thread (using the dequeue method) at a slightly later point in time.

 

Yes, the background thread would typically run a while loop and perform a WaitOne on the AutoResetEvent as means of syncronization before dequeuing each work item for processing. When there are no items to be processed, the thread goes to sleep and will not wake up again until another work item has been enqueued. If necessary, you can use Thread.Sleep(n) to yield once in while in order not to choke the CPU degrading responsiveness of you application.

 

Hope this helps!



#3 ziggurat29

ziggurat29

    Advanced Member

  • Members
  • PipPipPip
  • 244 posts

Posted 08 July 2013 - 01:15 PM

I'd like to add to hanzibal's suggestion that also, the interrupts are delivered on an internal worker thread that runs at Highest priority.  You don't really want to do much significant work there beyond hanzi's suggestion of queueing it for further processing on other threads (I'm speaking form personal experience on that; it's confusing, then amusing, to see the rest of the system running in slo-mo just because you're doing work in a button event handler rather than handing it off).

 

Lastly, as you've observed, the first 'main' thread seems internally to have some other duties.  It also has some scheduling oddities, e.g. as reported in this thread (no pun intended):

http://forums.netdui...ngs/#entry50924

I think most folks mask that effect because they sleep, but still it's interesting to be aware of it.



#4 Anshul

Anshul

    Advanced Member

  • Members
  • PipPipPip
  • 50 posts

Posted 08 July 2013 - 06:07 PM

Hi!

 

There's no special class for "Background threads", they are the same as any System.Threading.Thread. In the post you refer to, the term is used to denote a Thread who's purpose is to process data produced by an interrupt service routine (ISR) in order to avoid lenghty operations in the ISR itself.

 

The AutoResetEvent is used to have the "background thread" wait for a signal before going to work. It's a good example of the common producer/consumer pattern where the ISR is the producer and the background thread is the consumer.

 

You can use a System.Connections.Queue object for the ISR to quickly tuck work items away (using the Enqueue method) to be processed by the background thread (using the dequeue method) at a slightly later point in time.

 

Yes, the background thread would typically run a while loop and perform a WaitOne on the AutoResetEvent as means of syncronization before dequeuing each work item for processing. When there are no items to be processed, the thread goes to sleep and will not wake up again until another work item has been enqueued. If necessary, you can use Thread.Sleep(n) to yield once in while in order not to choke the CPU degrading responsiveness of you application.

 

Hope this helps!

 

That's interesting to know. I didn't know there is already a construct in C# to handle producer/consumer scenarios. Do you know of any good examples where this is implemented using the AutoResetEvent? Any for polling an input constantly, I'm guessing an ISR is not the correct choice?



#5 Anshul

Anshul

    Advanced Member

  • Members
  • PipPipPip
  • 50 posts

Posted 08 July 2013 - 06:09 PM

I'd like to add to hanzibal's suggestion that also, the interrupts are delivered on an internal worker thread that runs at Highest priority.  You don't really want to do much significant work there beyond hanzi's suggestion of queueing it for further processing on other threads (I'm speaking form personal experience on that; it's confusing, then amusing, to see the rest of the system running in slo-mo just because you're doing work in a button event handler rather than handing it off).

 

Lastly, as you've observed, the first 'main' thread seems internally to have some other duties.  It also has some scheduling oddities, e.g. as reported in this thread (no pun intended):

http://forums.netdui...ngs/#entry50924

I think most folks mask that effect because they sleep, but still it's interesting to be aware of it.

 

Yeah it seems that the main thread seems to become unresponsive if another thread goes in an infinite loop. It would seem like the main thread's priority is effectively set to very low since it's not able to respond to the interrupts from the debugger (at least that's the best explanation I can come up with).



#6 hanzibal

hanzibal

    Advanced Member

  • Members
  • PipPipPip
  • 1287 posts
  • LocationSweden

Posted 09 July 2013 - 07:17 AM

I was going to include some example code of a producer/consumer scenario but then I realized that the AutoResetEvent (ARE) is not really suitable for this. The reason is that you'd want precisely one item dequeued for every call to Set() and ARE cannot guarantee that.

 

Instead you need something with a counter in it that would increment with every Set() and decrement with every WaitOne(). In the regular framwork there is an synchronization object that works like this (can't remember its name right now) but sadly I don't think it's available in the micro framework. You need what I think is called a monitored queue.

 

Perhaps somebody else knows of how to correctly implement a monitored queue in .NETMF?

 

Correction: I made a typo before, it should have been System.Collections.Queue.






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.