Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Alle 100ms ein Kommando, was der User auch via Button frei triggern kann, geht nur manchmal
Janiiix3
myCSharp.de - Member



Dabei seit:
Beiträge: 42
Herkunft: Hannover

Themenstarter:

Alle 100ms ein Kommando, was der User auch via Button frei triggern kann, geht nur manchmal

beantworten | zitieren | melden

Nabend,

in einem Timer Event ( das alle 100ms) auftritt, sende ich Kommandos über die Serielle Schnittstelle und das ganze permanent.
Nun kann es vorkommen das der User während dies geschieht einen Button drücken kann um was anderes über die Serielle zu senden. Ab und zu klappt das auch.
Ab und zu geht es aber auch in die Hose.

Meine Frage jetzt. Was genau passiert wenn Daten gerade aus dem Timer Event geschickt werden und dann der User einen Button drückt? Wird das Timer Event dann direkt unterbrochen und bei dem Button Event weiter gemacht oder führt der Timer erst den kompletten Code aus?
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4028

beantworten | zitieren | melden

Das kommt auf den Timer drauf an. Wenn du den Windows.Forms.Timer benutzt, dann läuft dieser selber im UI-Thread, d.h. Timer-Code und Button-Code werden nacheinander ausgeführt. Bei den System-Timern kann jedoch aufgrund von Multithreading jeder der Methoden vorzeitig unterbrochen werden und sich die Ausgaben (über die Serielle Schnittstelle) mischen - du müßtest diese also dann selber synchronisieren.
private Nachricht | Beiträge des Benutzers
Janiiix3
myCSharp.de - Member



Dabei seit:
Beiträge: 42
Herkunft: Hannover

Themenstarter:

beantworten | zitieren | melden

Okay dann muss das Problem an einer anderen Stelle lauern.
In dem Seriellen Daten Empfangs Event, sammel ich solange die eingehenden Daten ein bis ich ein Kommando ganz empfangen habe. Klappt auch alles wunderbar.
Wird auch alles mit CRC auf Gültigkeit geprüft.
Drücke ich jetzt während der Timer läuft ( ist übrigens ein Forms Timer) empfange ich dann wohl ab und zu die Antwort nicht oder übersehe sie???
Wenn es am Ablauf nicht liegen kann muss ich diese Nachricht wohl nicht mitbekommen oder irgendwie verwerfen..
Vill. hat ja jemand einen Tipp für mich?


       int length = 0;
        byte bytesToReceive = 0;
        byte[] buffer = new byte[100];

        private void Client_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            /*  Empfangene Daten abholen
            */
            try
            {
                length += Client.Read(buffer, length, 50 );
            }
            catch { }
            

            /*  Kommando Start Parsen
             *  Rückgabewert: - 1 = Kein Start gefunden..
            */
            int index = Cmd.ParseCommandoStart(buffer);
            if (index != -1)
            {
                /*  Anzahl der zu empfangenen Bytes auslesen
                    * HIER WIRD NOCH KEIN CRC BERECHNET!
                    * Es könnten Übertragungsfehler nicht erkannt werden..
                */
                bytesToReceive = buffer[index + (byte)Cmd.Communication_Header_Enum.CMD_HEADER_LENGHT];
            }

            /*  Wurden alle Bytes empfangen?
                *  Wenn nicht, direkt wieder raus hier!
            */
            if (length < bytesToReceive)
            {
                return;
            }
            else
            {
                length = 0;
                bytesToReceive = 0;
            }

            /*  Kommando untersuchen..
            */
            Cmd.ParseCommando( buffer, ref Cmd.CommandoParsed );

            manualResetEvent.Set();
        }

private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4028

beantworten | zitieren | melden

Wo wartest du denn auf den manualResetEvent? Dieses Warten blockiert natürlich den entsprechenden Thread.
private Nachricht | Beiträge des Benutzers
thomas.at
myCSharp.de - Member



Dabei seit:
Beiträge: 102
Herkunft: Österreich / Wien

beantworten | zitieren | melden

Hallo

stell Deine Befehle die Du senden möchtest (Timer, User) in eine Queue und arbeite diese sequentiell ab. Und zwar immer erst dann, wenn eine Antwort vollständig empfangen wurde. Ich vermute mal, dass Deine Peripherie durcheinander kommt, wenn es beim Senden eine neue Nachricht bekommt.

Thomas
private Nachricht | Beiträge des Benutzers
Janiiix3
myCSharp.de - Member



Dabei seit:
Beiträge: 42
Herkunft: Hannover

Themenstarter:

beantworten | zitieren | melden

Okay. Ist das so eine Art Ringpuffer?
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4028

beantworten | zitieren | melden

Nicht unbedingt, eine Warteschlange (Queue) arbeitet generell ersteinmal nach dem FIFO-Prinzip (ob der Speicher dabei "unendlich" ist oder limitiert, liegt an der entsprechenden Implementierung).

Im .NET-Framework gibt es die threadsicheren Container im System.Collections.Concurrent Namespace, d.h. nutze also die ConcurrentQueue<T>, damit 'Producer' und 'Consumer' aus verschiedenen Threads sicher darauf zugreifen können.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15827
Herkunft: BW

beantworten | zitieren | melden

Ich empfehle an dieser Stelle zB https://github.com/jbogard/MediatR, der genau das macht und einem die gesamte Infrastruktur abnimmt.

Das bedeutet, dass man würde in diesem Fall einen Command via Send in die Queue schreiben und ein entsprechender Handler würde das Abarbeiten durchführen.

Das entspricht in etwa dem CQS bzw CQRS Pattern - nur alles InProcess.
private Nachricht | Beiträge des Benutzers