Main Site Documentation

Question about events in NETMF and Gadgeteer


#1

I was used to write Gadgeteer Applications but now I have to port things to pure NETMF.
There seem to be differences how to throw events.
In a Gadgeteer Application I had to use code like this:


protected virtual void OnEventWasThrown(string pTheMessage)
{
            if (onEventWasThrown == null)
            {
                onEventWasThrown = OnEventWasThrown;
            }
            if (Program.CheckAndInvoke(EventWasThrown, onEventWasThrown, pTheMessage))
            {                
                  EventWasThrown(pTheMessage);
            }            
 }

In a NETMF application I could not manage to use the Program.CheckAndInvoke method, so I supposed that I could not access members of the main thread as I thought that they were out of the scope.
Surprisingly I can!! (see example).
However is it correct to use the events without checking the need to invoke?
How is it done correctly?

Example:


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

namespace EventThrowTest_NETMF
{
    public class Program
    {
        static EventThrower myEventThrower;
        static string messageFromMainThread = "This message from the main thread was printed";
        
        public static void Main()
        {
            Debug.Print(Resources.GetString(Resources.StringResources.String1));
            myEventThrower = new EventThrower();
            myEventThrower.EventWasThrown += myEventThrower_EventWasThrown;
            myEventThrower.Start();
            while (true)
            { }
        }

        static void myEventThrower_EventWasThrown(string pTheMessage)
        {
            Debug.Print(pTheMessage);
            Debug.Print(messageFromMainThread);
        }
    }

    //******************************************************
    class EventThrower
    {
        public delegate void TheEventHandler(string theMessage);
        public event TheEventHandler EventWasThrown;
        private TheEventHandler onEventWasThrown;
        private Thread workThread;

        public EventThrower()
        {
            Debug.Print("Class EventThrower instantiated");
            workThread = new Thread(new ThreadStart(runWorkThread));
        }

        void runWorkThread()
        {
            Debug.Print("I'm in the workThread");
            OnEventWasThrown("This message from EventThrower thread was printed");
        }

        public void Start()
        {
            workThread.Start();
        }

        protected virtual void OnEventWasThrown(string pTheMessage)
        {
            if (onEventWasThrown == null)
            {
                onEventWasThrown = OnEventWasThrown;
            }
            /* this is the way to do it in a Gadgeteer application
            if (Program.CheckAndInvoke(EventWasThrown, onEventWasThrown, pTheMessage))
            {
                EventWasThrown(pTheMessage);
            }
            */
            EventWasThrown(pTheMessage);
        }
    }
}


#2

@ RoSchmi - Gadgeteer did some funny stuff with an event thread. I have never had to worry about such a thing with pure NETMF. Are you trying to serialize some processing? If you want to create a single thread for processing events, then you will need to use a queue, in sprite of the producer/consumer pattern.


#3

@ Mike - I want to have a Class where a separate thread is started. This thread reads from the serial port (perhaps makes same parsing) and sends a resulting string via Delagate/Event to the main thread where some fields shall be altered according to the contents of the received message. I can access the fields in the main Class Program but I am surprised that I can, as in e.g. a Windows Forms application I can not. I’m only interested to find a solution for NETMF which will work in every case.


#4

@ RoSchmi - In a Forms application, you can reference the fields of the main window if you have a reference to it. But, if you try to change the property of a GUI control, you will get a cross threading exception. You can only manipulate controls in the thread that created them. That is why invoke is used in a Forms application to get to the main thread.

So, you don’t need the main thread to access properties of the main class. Of course, you are going to need locking if you will be changing properties in the main class from multiple threads.

For a start, on a producer/consumer pattern, which can be used to pass data from a serial port thread to another thread, look at http://stackoverflow.com/questions/1656404/c-sharp-producer-consumer. This is very old styled code. I would use an AutoReset object to coordinate when work is ready.,


#5

@ Mike - thanks, seems that I mixed some things up.
Yes, you are right, in Windows Forms in the eventhandler I can write data that came as eventargs to fields of the Form Class without problems. Only when I write somehing that was transmitted with the eventargs to a control (e.g. TextBox) I get an exception.
I can even manipulate the controls in the eventhandler, e.g. write directly textbox1.Text = “Hello World” without exception.

However, so in NETMF there seems to be no problem to throw an event without this Gadgeteer specific “Program.CheckAndInvoke”


#6

@ RoSchmi

Absolutely!