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

multi threaded webserver


  • Please log in to reply
9 replies to this topic

#1 stotech

stotech

    Advanced Member

  • Members
  • PipPipPip
  • 143 posts
  • LocationAustralia

Posted 06 August 2012 - 01:08 PM

Hi Guys, First I'd like to thanks to everyone who helps out in the forums. Studying all of your guides and comments is

better than school for me. I very new to programming but I'm usually a pretty quick learner. I'm hoping to implement a

system using the code at http://www.schuurman...r-netduino-plus . It's a clever little web

server for starting and stopping things on the board. I got it working just how it describes without any problems. I could

go to http://ipaddress/settled/on and it worked as it should. But I'm trying to get it to do more advanced things now like

running other scripts so to speak. For example http://ipaddress/flashled/on . I played with the code and I was sort of

able to achieve this. But then I couldn't stop it from flashing because it was stuck in a loop. So I decided it would be

good if for the future I started these advanced routine's in there own thread. So I did. But when I run blinkythread.abort

it throws an exception. Maybe I'm going about it all the wrong way. What I'm hoping to achieve is to be able to send a get

request through a browser like http://ipaddress/setbath/36 . And have another thread start a new cs file and go about

opening the solenoid's and reading the temperature to fill it to the right temp. But while that tread is still executing

still be able to receive cmd's to turn on light's and stuff. Hope this makes sense. I've read the book about threading a

couple of times and can't quite grasp it.
I'm trying to configure this as a base framework to start all my gadgets off. Once I'm able to start and stop complex

operations in their own thread and kill them at will. I'll be laughin.


here is how I've changed the code so far and got stuck.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using Blinq.Netduino.Web;

namespace ServerExample
{
    /// <summary>
    /// Example for using the Blinq.Netduino.Webserver class
    /// </summary>
    public class Program
    {

        public static OutputPort onBoardLed = new OutputPort(Pins.ONBOARD_LED, false);
        
        public static void Main()
        {
            // Instantiate a new web server on port 80.
            WebServer server = new WebServer(80);

            // Add a handler for commands that are received by the server.
            server.CommandReceived += new WebServer.CommandReceivedHandler(server_CommandReceived);

            // Add a command that the server will parse.
            // Any command name is allowed; you will decide what the command does
            // in the CommandReceived handler. The server will only fire CommandReceived
            // for commands that are defined here and that are called with the proper
            // number of arguments.
            // In this example, I define a command 'setLed', which needs one argument (on/off).
            // With this statement, I defined that we can call our server on (for example)
            // http://[server-ip]/setled/on
            // http://[server-ip]/setled/off
            server.AllowedCommands.Add(new WebCommand("setled", 1));
            server.AllowedCommands.Add(new WebCommand("flashled", 1));

            // Start the server.
            server.Start();

            // Make sure Netduino keeps running.
            while (true)
            {
                Debug.Print("Netduino still running...");
                Debug.Print("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString());
                Thread.Sleep(10000);
            }
        }

        /// <summary>
        /// Handles the CommandReceived event.
        /// </summary>
        private static void server_CommandReceived(object source, WebCommandEventArgs e)
        {

            Debug.Print("Command received:" + e.Command.CommandString);

            switch (e.Command.CommandString)
            {
                case "setled":
                    {
                        // Do you stuff with the command here. Set a led state, return a
                        // sampled value of an analog input, whatever.
                        // Use the ReturnString property to (optionally) return something
                        // to the web user.

                        // Read led state from command and set led state.
                        bool state = ( e.Command.Arguments[0].Equals("on") ? true : false);
                        onBoardLed.Write(state);

                        // Return feedback to web user.
                        e.ReturnString = "<html><body>You called SetLed with argument: " + e.Command.Arguments[0].ToString() + "</body></hmtl>";
                        break;
                    }
                case "flashled":
                    {
                        
                        bool state = (e.Command.Arguments[0].Equals("on") ? true : false);
                        {
                            blinky blinkyobject = new blinky();
                            Thread blinkythread = new Thread(blinkyobject.blinkygo);

                            if (state == true)
                            {
                                Debug.Print("blinky start");
                                blinkythread.Start();
                                e.ReturnString = "<html><body>You called FlashLed with argument: " + e.Command.Arguments[0].ToString() + "</body></hmtl>";

                            }
                            if (state == false)
                            {
                                //Debug.Print("blinky stop");
                                blinkyobject.RequestStop();
                                Thread.Sleep(500);
                                blinkythread.Join();
                                Debug.Print("main thread: Worker thread has terminated.");
                                e.ReturnString = "<html><body>You called FlashLed with argument: " + e.Command.Arguments[0].ToString() + "</body></hmtl>";
                            }
                        }
                        break;
                    }
            }

        }
    }
}



Thanks in advance.

also, sorry to the moderators if I sent this twice. Browser issues.

#2 AxelG

AxelG

    Advanced Member

  • Members
  • PipPipPip
  • 52 posts

Posted 06 August 2012 - 03:09 PM

... So I did. But when I run blinkythread.abort

it throws an exception. Maybe I'm going about it all the wrong way. What I'm hoping to achieve is to be able to send a get

request through a browser like http://ipaddress/setbath/36 .



Hi Grant:
Maybe instead of just aborting the thread you could signal the Blinky thread to shutdown more gracefully. One way is to set up a simple event and trigger that event from your main code. This way the Blinky thread will close and perform any cleanup. You could put a timeout waiting for that thread to end before forcing the abort. Also, make sure the thread is still alive before calling the abort.

This tutorial may be helpful: Events
And this one on threading: Threading

Both of these helped me understand .NET threads and events.

#3 stotech

stotech

    Advanced Member

  • Members
  • PipPipPip
  • 143 posts
  • LocationAustralia

Posted 07 August 2012 - 03:08 AM

I read the links and have a better understanding now about gracefully killing threads. But this is killing me. I can't for the life of me stop this while loop and close the thread. I tried setting a volatile bool and it doesn't work. http://forums.netdui...h__1#entry13901 I've attached the project. Any help much appreciated. version 6 was broken completely. just ignore it.

#4 AxelG

AxelG

    Advanced Member

  • Members
  • PipPipPip
  • 52 posts

Posted 07 August 2012 - 01:29 PM



I've attached the project. Any help much appreciated.


My ND+ is in use, so I could not run this code. Reading it, I suspect this {below} part of the code might be causing your trouble. From what I can gather in reading the source, this code gets called once to start flashing, and then again to stop flashing. That will create two threads for blinky: once when it gets the "on" command, and then creates a new thread when it gets the "off" command. I suspect that the "off" command does kill the thread started by the "off" command, but the "on" command thread is still running. If you look at the debugger output, you can see when the threads terminate to verify; compare that to when new threads start.

Look for something like the following: "The thread '<No Name>' (0x14) has exited with code 0 (0x0)." in your debug output.

One way to deal with this is to use managed threads and then you can tell which threads are running. {great way to learn about thread pools!} An alternative is to store the state of blinky in a static variable in main() so you can do two things: 1) make sure two "on" commands are not called without first calling an "off", 2) verify blinky is running before you try and kill it. (This will also require that blinkyobject be declared as static in main() as well so you can kill in one thread what was started in another)

[Disclaimer: There will be various opinions as to the best solution; I am just suggesting a couple that come to mind at the moment :) ]

Happy blinking! I hope this blurb helps get this solved for you.

               case "flashled":
                    {
                        
                        bool state = (e.Command.Arguments[0].Equals("on") ? true : false);
                        {
                            blinky blinkyobject = new blinky();
                            Thread blinkythread = new Thread(blinkyobject.blinkygo);

                            if (state == true)
                            {
                                Debug.Print("blinky start");
                                blinkythread.Start();
                                e.ReturnString = "<html><body>You called FlashLed with argument: " + e.Command.Arguments[0].ToString() + "</body></hmtl>";

                            }
                            if (state == false)
                            {
                                //Debug.Print("blinky stop");
                                blinkyobject.RequestStop();
                                Thread.Sleep(500);
                                blinkythread.Join();
                                Debug.Print("main thread: Worker thread has terminated.");
                                e.ReturnString = "<html><body>You called FlashLed with argument: " + e.Command.Arguments[0].ToString() + "</body></hmtl>";
                            }
                        }



#5 stotech

stotech

    Advanced Member

  • Members
  • PipPipPip
  • 143 posts
  • LocationAustralia

Posted 07 August 2012 - 01:47 PM

Thanks Mate. I'll try to implement those changes over the next few days and I'll get back with the results soon.

#6 stotech

stotech

    Advanced Member

  • Members
  • PipPipPip
  • 143 posts
  • LocationAustralia

Posted 08 August 2012 - 08:54 AM

I'm not sure that I'm always going to be able gracefully shutdown all the threads I'm planning on building. This is going onto a factory to automate some simple vat wash procedures etc. There will be a dozen or so different combinations of motors, sensors and taps all opening and closing etc. I want to be able to call different procedures to start over http. I wanted to use threads so if they start 1 type of procedure, and change there mind, so start another one without closing the first. Since they are using the same motors etc. The start of each procedure should terminate any previous thread regardless of where it is up to. Is this possible the route I'm going down. How can I kill these procedures[threads?] regardless of where they are up to? Thanks in advance.

#7 Coyttl

Coyttl

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts
  • LocationSilver Spring, MD, USA

Posted 08 August 2012 - 02:54 PM

Believe you can simply kill it - thread.Abort(); That will cause it to throw a "ThreadInterruptedException" on the next line it's about to execute. --Me.

#8 Tom K.

Tom K.

    New Member

  • Members
  • Pip
  • 1 posts

Posted 08 August 2012 - 08:43 PM

I believe you could do it a couple of ways.

1. Using Thread.Abort() and the catch the exception.
static void backgroundThread() 
{
    try
    {
        // Do background work here.
    }
    catch (ThreadAbortException)
    {
       // Do nothing here to ignore the error.
    }
}

2. Set a variable used to return out of the background thread.
bool letThreadRun = false;
static Thread backgroundThread;
        
static void startThread() 
{
    letThreadRun = true;
    backgroundThread = new Thread(runBackgroundThread); 
    backgroundThread.Start();
}

static void stopThread() 
{
   letThreadRun = false;
}

static void runBackgroundThread() 
{
    while (letThreadRun)
    {
        // Do some background work
        if (!letThreadRun)
        {
            return;
        }
        // Do some more background work
        if (!letThreadRun)
        {
            return;
        }
        // Do some more background work
        if (!letThreadRun)
        {
            return;
        }
    }
     
}
If your background thread doesn't take very long before it loops then you don't need the if statements inside the while loop.

#9 stotech

stotech

    Advanced Member

  • Members
  • PipPipPip
  • 143 posts
  • LocationAustralia

Posted 08 August 2012 - 11:48 PM

Thankyou so much. I think I can work this out now. I'll let you know how I go. Thanks Again.

#10 Coyttl

Coyttl

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts
  • LocationSilver Spring, MD, USA

Posted 08 August 2012 - 11:52 PM

For the record, the second way is the better, safer way. :)




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.