C# CF3.5 wie mitteilungen von einem Thread in anderen übergeben

Blue_Fox

Mitglied
Hi Leute

ich hoff hier bin ich richtig...

Ich habe folgendes Problem:
Ich steuere mit einem Touchpanel über den Comport einen uC an. Dies funktioniert auch schon recht gut, nur sollte jetzt der uC auch noch jederzeit etwas an das Touchpanel schicken können! Aber ich kann den ComPort nur ein mal öffnen...

Meine Idee war jetzt, einen Thread aufzumachen, der ständig auf empfangen ist. Wenn ich was an den uC senden will, setzt ich den Thread in den Sleepmodus, öffne den Comport neu, sende, schließe den Comport wieder und lasse den Thread weiterlaufen.

Ich weiß nicht mal ob das so funktionieren würde. Das größte Problem ist aber, dass ich aus meinem "Zuhör"Thread an mein normal laufendes Programm eine Meldung und neue variablen übergeben müsste, wenn der uC was geschickt hat.

Beim CF3.5 funktioniert leider kein Interrupt und mit einer exception "vernichte" ich meinen "Zuhör"Thread...

Am besten waere ein Event, mit dem ich eine Parameterliste zurueckgeben koennte....

Wie könnte ich jetzt da eine Kommunikation aufbaun?

mfg
Blue Fox
 
Zuletzt bearbeitet:

Shakie

Erfahrenes Mitglied
Ich glaube, hier liegen zweierlei Probleme vor: einmal die Kommunikation zwischen Threads und einmal die Kommunikation mit der seriellen Schnittstelle.
Ich vermute, du verwendest die SerialPort-Klasse? Von dieser brauchst du für deinen ganzen Programmablauf nur eine einzige Instanz und der ComPort muss auch nur ein einziges mal geöffnet werden.
Denn du kannst die Instanz sowohl zum Empfangen als auch zum Senden verwenden. Zum Lesen gibt es mehrere Methoden, deren Namen alle mit "Read..." anfangen (siehe MSDN). Zum Schreiben gibt es analog die Write- und WriteLine-Methoden.
Außerdem gibt es das DataReceived-Event, das dir mitteilt, wann Daten gesendet wurden. Sobald das Event eintritt solltest du eine der Read-Methoden ausführen.
Diese Kommunikation erledigst du in einem Thread.
Den UI-Thread musst du dann nochmal benachrichtigen, dass etwas passiert ist, zum Beispiel mittels Invoke.
 

Blue_Fox

Mitglied
Hi Shakie

Das mit dem ComPort oeffnen is ne gute Nachricht!! :D Habs auch gleich umgesetzt...

Das DataReceived-Event ist fuer meine Zwecke perfekt!! DANKE!!

So aber jetzt kommt ein weiteres Problem...

Ich wollte jetzt die kommuniktaion rein auf Events basieren lassen. Wenn ich was empfange habe, is ja auch ganz sinnvoll, da es ja sein kann, dass das Hauptprogramm gar nicht darauf gefasst ist. Nur das senden ueber ein Event funktioniert nicht...

Da finde ich die Invoke-Methode recht interessant. Nur kapiers ich noch nicht ganz!! :( erschwerend kommt da hinzu, dass ich fuer WinCE programmiere!!

Kannst mir da ne bitte ne kleine Starthilfe geben? und kann ich mit der Invoke-Methode einen Rueckgabewert bekommen?

mfg

Blue Fox
 

Shakie

Erfahrenes Mitglied
Nur das senden ueber ein Event funktioniert nicht...
Definier mal bitte, was du damit meinst. "Senden über Event" ergibt für mich keinen Sinn. Oder meinst du Button-Click-Events?
Von der Invoke-Methode kannst du keinen Rückgabewert erhalten, schließlich wechselst du damit den Thread! (ausser du verwendest BeginInvoke+EndInvoke)
Invoke sollte auch mit dem Compact Framework funktionieren.
Starthilfen gibt es auch genügend im Netz. Such einfach mal nach "C# multithreading tutorial"!
 

Blue_Fox

Mitglied
Definier mal bitte, was du damit meinst. "Senden über Event" ergibt für mich keinen Sinn. Oder meinst du Button-Click-Events?
!

Sorry f[r mich klingt das immer so logisch, ich arbeite ja damit....

Also Ich hab hab mir 2 Events zusammengestellt. Eines wir ausgeloest, wenn ich etwas von der Seriellen Schnittstelle bekomme und mein Hauptprogramm davon was mitbekommen sollte. Hier uebergebe ich auch daten mit einem selbst erstellten Event Arg.

Jetzt wollte ich das gleiche auch als Befehl zum Senden ueber die serielle Schnittstelle verwenden. In der Theorie funktionierts, nur kann ich dieses Event nicht deklarieren, da ich mir eine endlosschleife baue, wenn ich meinen Thread mit "SerialThread serialTh = new SerialThread();" bekannt mache, da ich ja vom anderen Event schon meine andere Klasse eingebunden habe...

Beispiel:
Code:
 class SERIAL2
    {
        SERIALThread serialthread = new SERIALThread();
        UDPServer udpserver = new UDPServer();
        
        List<GatewayList> Comlist = new List<GatewayList>();
/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Event for sending commands ------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

        public byte[] serialSend(byte[] HAddress, byte RGBRed, byte RGBGreen, byte RGBBlue)
        {
            byte[] message = new byte[8];

            HAddress.CopyTo(message, 1);
            message[5] = RGBRed;
            message[6] = RGBGreen;
            message[7] = RGBBlue;
            message[0] = 0x87;

            OnSerialwriteEvent(new SerialEventArgs(message));

            WaitforAnswer = true;

            while (WaitforAnswer) ;

            return Returnmessage;
        }

        public event EventHandler<SerialEventArgs> SerialwriteEvent;

        protected virtual void OnSerialwriteEvent(SerialEventArgs e)
        {
            EventHandler<SerialEventArgs> serialwriteevent = SerialwriteEvent;
            if (serialwriteevent != null)
            {
                serialwriteevent(this, e);
            }
        }

/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Event for sending commands end --------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Event for receiving light state changed -----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

        private void Serialrec_SerialrecEvent(object objSender, SerialEventArgs e)
        {
            switch (e.SerialData[0])
            {
                case 0xAC :
                    verifyMessage(e.SerialData);

                    WaitforAnswer = false;

                    break;

                case 0xFE :

                    HWAddresse[0] = e.SerialData[1];
                    HWAddresse[1] = e.SerialData[2];
                    HWAddresse[2] = e.SerialData[3];
                    HWAddresse[3] = e.SerialData[4];

                    for (int i = 0; i < Comlist.Count; i++)
                    {
                        if (HWAddresse == Comlist[i].GetHardwareaddress())
                        {
                            udpserver.UDP_Server_Light(Comlist[i].GetGroup(), Comlist[i].GetAddress());
                            break;
                        }
                    }
                    break;

                case 0xBD :
                    // ToDo: Gateway ready
                    break;

                default :
                    // ToDo: Error
                    break;
            }
        }

/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Event for receiving light state changed end--------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

Code:
 class SERIALThread
    {
        TIMEOUT TimeoutObject = new TIMEOUT();
        SERIAL2 serialcom2 = new SERIAL2();

        private Thread timeout;
        private SerialPort ComPort;

        byte[] data = new byte[7];

/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Read message --------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

        private void SerialRead(byte cmd, byte[] data)
        {
            byte[] message = new byte[8];

            message[0] = cmd;
            data.CopyTo(message, 1);

            OnSerialreceiveEvent(new SerialEventArgs(message));
        }

        private void DataReceviedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            byte incomingMessage = 0x00;                // only 0x87: 0x01 / 0x87 + 0xFE: 0x02 / 0x87 + 0xAC: 0x04 / 0x87 + 0xBD: 0x08
            ushort receiveddata = 0x00;

            SerialPort sp = (SerialPort)sender;

            // Timeout
            timeout = new Thread(TimeoutThread);
            timeout.IsBackground = true;
            TimeoutObject.TimeOutEvent += TimeOut_TimeOutEvent;

            switch (incomingMessage)
            {
                case 0x00:
                    if (Encoding.ASCII.GetByteCount(sp.ReadExisting()) == 0x87)
                    {
                        timeout.Start();
                        incomingMessage = 0x01;
                    }
                    else
                    {
                        // ToDo Error
                    }
                    break;

                case 0x01:
                    switch (Encoding.ASCII.GetByteCount(sp.ReadExisting()))
                    {
                        case 0xFE :                  // light changed manually
                            incomingMessage = 0x02;
                            break;

                        case 0xAC :                  // normal light changed 
                            incomingMessage = 0x04;
                            break;
                        
                        case 0xBD :                  // gateway ready
                            incomingMessage = 0x08;
                            break;
                    }
                    break;

                case 0x02:
                    receiveddata++;
                    data = Encoding.ASCII.GetBytes(sp.ReadExisting());

                    if (receiveddata == 6)
                    {
                        timeout.Abort();
                        receiveddata = 0x00;
                        SerialRead(0x02, data);
                    }
                    break;

                case 0x04 :
                    receiveddata++;
                    data = Encoding.ASCII.GetBytes(sp.ReadExisting());

                    if (receiveddata == 3)
                    {
                        timeout.Abort();
                        receiveddata = 0x00;
                        SerialRead(0x04, data);
                    }
                    break;

                case 0x08 :
                    receiveddata++;
                    data = Encoding.ASCII.GetBytes(sp.ReadExisting());

                    SerialRead(0x08,data);
                    break;

                default:
                    break;
            }
        }

/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Read message end ----------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Send message -------------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

        private void Serialwrite_SerialwriteEvent(object objSender, SerialEventArgs e)
        {
           ComPort.Write(e.SerialData, 0, e.SerialData.Length);
        }

/*----------------------------------------------------------------------------------------------------------------------------*/
/*------ Send message end ---------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------------------------------------------------*/

Ich werde jetzt mal versuchen, den Sendebefehl mit einem Invoke zu versuchen....

mfg
Blue Fox
 

Shakie

Erfahrenes Mitglied
Es macht ein bisschen den Eindruck auf mich als wäre dir nicht ganz klar, was ein Event ist. Ein Event ist, 1-zu-1 übersetzt, ein Ereignis. Das heißt es muss etwas passieren, und dann wird darauf reagiert.
Im Beispiel des DataReceived-Events passiert also, dass Daten empfangen werden und reagiert wird mit dem Aufruf deiner DataReceviedHandler-Funktion.
Was soll bei dir das Ereignis sein, das das Senden von Daten auslösen soll?
 

Blue_Fox

Mitglied
Hi Shakie

Da ich ja von aussen auf den Thread keinen einfluss habe, wollte ich einfach dieses Sendeevent selber ausloesen. Das geht eigentlich wunderbar und hab ich schon einmal verwendet um mein Programm zu benachrichtigen, dass was passiert ist.

Jetzt hab ich aber mein Programm vollstaendig umgeplant! Jetzt mach ich eine Klasse (vorher warn es 2) und ich steuere den Zugriff auf die serielle Schnittstelle mit einem Mutex.

Somit brauch ich nur das Empangsevent... und alles wird etwas leichter...

mfg

Bastian
 

Neue Beiträge