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

Threading Problems After Deploy


  • Please log in to reply
5 replies to this topic

#1 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 18 March 2011 - 11:18 PM

I'm playing with some code to drive a Sparkfun Serial LCD and ran into some timing issues which caused a garbled display unless I put an 80ms delay (Thread.Sleep) between each write operation.

This was fine for testing but with the delay on the main thread it slows everything down whenever I write to the LCD. So I thought it might be a good idea to put the write operation on its own thread like this:

private void Write(byte[] data)
{
	new Thread(delegate { this._Write(data); }).Start();
}

private void _Write(byte[] data)
{
	this.port.Write(data, 0, data.Length);
	Thread.Sleep(80);
}

This code works fine as long as the debugger is attached but as soon as I deploy and reset the Netduino, the display ceases to function. The code itself is still operational (no exceptions, as far as I can tell) but the display thread doesn't seem to be doing anything. If I remove the threading and write to the device directly everything is fine again.

Is this expected behaviour? Is there some better way of doing this that I don't know about?

- Adam

[N+ firmware v4.1.1.0 ALPHA7]

#2 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 19 March 2011 - 02:17 AM

This code works fine as long as the debugger is attached but as soon as I deploy and reset the Netduino, the display ceases to function.

I believe the problem you are seeing is because the code doesn't actually do what you want it to do. You want an 80 ms delay between writes, however in this code the writes can all end up stacked on top of each other. If this doesn't make sense, consider this example:

public static void Main() {
  var bytes=new byte[XXX];
  //fill bytes with message 1
  driver.Write(bytes); //line A
  //fill bytes with message 2
  driver.Write(bytes); //line B
  //fill bytes with message 3
  driver.Write(bytes); //line C
}

This is one possible execution trace of this program:
  • Line A executes, Thread 1 is started
  • Line B executes, Thread 2 is started
  • Line C executes, Thread 3 is started
  • Thread 1 calls this.port.Write()
  • Thread 2 calls this.port.Write()
  • Thread 3 calls this.port.Write()
  • Thread 1 sleeps for 80 ms
  • Thread 2 sleeps for 80 ms
  • Thread 3 sleeps for 80 ms
This is not what you wanted, as all three calls to this.port.Write() could be happening at about the same time. Rather than a delay between messages, you're creating a bunch of threads who all eagerly try to write at the same time and then whose last act before dying is to sleep 80 ms.

Footnote: my example also has another problem, in that the contents of the byte array are getting overwritten before they are being sent. This may or may not be a problem in your code. It depends on the structure of your code.

I don't know why it's working in the IDE but it's possible that the timing characteristics are different enough that you're getting away with the race.

#3 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 19 March 2011 - 04:27 AM

I believe the problem you are seeing is because the code doesn't actually do what you want it to do. You want an 80 ms delay between writes, however in this code the writes can all end up stacked on top of each other. If this doesn't make sense, consider this example:


You're absolutely right, that's exactly what's happening.

Thanks for the help.

- Adam

#4 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 19 March 2011 - 07:03 AM

You're absolutely right, that's exactly what's happening.


Have you thought about using a queue and a timer?

Have a class which holds the data and the timer. Provide an add method which adds data to the queue and starts the timer. The timer event takes data out of the queue and writes the data. If the queue is not empty it restarts the 80ms timer.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#5 demonGeek

demonGeek

    Advanced Member

  • Members
  • PipPipPip
  • 42 posts
  • LocationCanada

Posted 19 March 2011 - 04:53 PM

Have you thought about using a queue and a timer?

Have a class which holds the data and the timer. Provide an add method which adds data to the queue and starts the timer. The timer event takes data out of the queue and writes the data. If the queue is not empty it restarts the 80ms timer.

Regards,
Mark

Thanks Mark, that would certainly work.

I've also been wondering about some kind of thread blocking mechanism.

The Sparkfun serial backpack has an on-board buffer and the timing issues seem to be centred around marshalling the data to that buffer.

I'll have to play with it some more.

- Adam

#6 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 20 March 2011 - 06:26 AM

Thanks Mark, that would certainly work.

I've also been wondering about some kind of thread blocking mechanism.


You would need to implement some locking here too as it is possible to be part way through an Add operation at the time an event is triggered for a removal. That could get nasty.

regards
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter





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.