Laden...

Probleme bei Hardware-Ressourcenverteilung unter WinCE

Erstellt von macke_a vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.747 Views
M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren
Probleme bei Hardware-Ressourcenverteilung unter WinCE

Ich habe einen WinCE Embedded Rechner (806MHz, 128MB RAM) auf dem primär ein Prozess mit zwei unterschiedlichen Aufgaben laufen. Zum einem muss ich die Kommunikation mit einer externen Hardware aufrecht halten, indem ich auf Anfrage der Gegenstelle alle 100ms über die serielle Schnittstelle ein Telegramm sende und zum anderen eine Navigationssoftware deren Informationen auf einem 7" Monitor dargestellt wird.

Jetzt habe ich das folgende Problem:
Sobald ich eine Route mit der Navigationssoftware berechnen lasse, bin ich nicht mehr in der Lage empfangene Telegramme, für die Berechnungszeit der Route von ca. 4Sekunden, auszuwerten.

Die Navigationssoftware "klaut" mir die Ressourcen in meinem Prozess, sodass ich überhaupt nicht mehr auf empfangene Telegramme reagieren kann. Ich bekomme vom Betriebssystem keine Rückmeldung, dass Daten auf der seriellen Schnittstelle empfangen worden sind!

Ich habe das Programm mit der ich die serielle Schnittstelle und die Navigationssoftware starte "einfach herunter" geschreiben. Thread Programmierung und die Vergabe von Prioritäten habe ich nicht beachtet.

Was müßte ich vom Prinzip der Programmierung ändern, dass wenn eine Route berechnet wird, ich noch Telegramme auswerten und beantworten kann. Ich suche nach Möglichkeiten um den Fehler zu beheben. Schließlich kann ich dem Betriebssystem doch vorgeben, welche Aufgabe höhere Prioritäten habe als andere. Die Berechnung der Route kann ich auch auch 7Sekunden dauern, wenn ich dafür in der Lage bin, die seriellen Telegramm auszuwerten.

Ich freue mich auf Antworten und werde auch auf direkte Fragen von Euch eingehen!

Vielen Dank für Eure Bemühungen!

Gruss macke_a

B
101 Beiträge seit 2008
vor 15 Jahren

Halloe macke_a,

du hast ja selber schon das Wörtchen "Thread" erwähnt.
Threads sind für solche Dinge immer sehr sinnvoll, Beispiel:


class Navi
{
     public Navi ()
     {
          
          Thread t = new Thread(new ThreadStart(getTelegramm));
          //Navikram

          //Route berechnen Kram
     }

     protected void getTelegramm()
     {
          for(;;)
          {
               //Telegramme erhalten und so weiter
          }
     }

     public static void Main()
     {
           new Navi();
     }
}

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren

Hallo bluedraggon,
danke für den Beitrag.

Wie ich bereits vermut habe ist eine Thread Programmierung von nöten um eine korrekte Abarbeitung meiner Programmierung zu gewährleisten. Demmach müßte ich meine Programmstruktur von Grund auf ändern, um solche Performance Probleme in den Griff zu kriegen.

Sehe ich das richtig?

Gruss macke_a

B
101 Beiträge seit 2008
vor 15 Jahren

Im Endeffekt, werden die Threads intern auch nur in eine Warteschleife gelegt, für den Benutzter sieht es nach aussen hin so aus, als ob beide Prozesse gleichzeitig behandelt werden. Aber in Wirkllichkeit werden sie auch nur immerwieder nacheinander behandelt.
Ich kenne deinen Code nicht und weiß nicht was du falsch oder richtig, gut oder schlecht in deiner Programmierstruktur machst. Viele Wege führen nach Rom 😉
Aber wenn du selber schon sagst, dass du den Code nur "einfach heruntergeschrieben" hast. Dann solltest du noch mal den Code neu schreiben oder modifizieren (nur wenn merkliche Performence-Probleme auftreten).

Achja und während du auf die Telegramme zugreifst, solltest du sie vorher noch mit lock sperren für die dauer der Behandlung, damit vermeidest du, dass während der Auswertung oder was auch immer du damit machst, die Endlosschleife im Thread, die Telegramme manipuliert.

mfg
bluedragon

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren

Danke für den Beitrag. Eine prinzipielle Frage bleibt mir allerdings noch offen, was die Programmierung mit C# betrifft.

Ist es denn sinnvoll die Programmteile in mehrere Threads zu fassen? Muss ich von Grund auf diese Beziehung einhalten?

Bis jetzt habe ich meine Programme ohne Threads geschrieben. Dabei habe ich eine grafische Oberfläche auf einem 7" Monitor dargestellt. Bei jedem Button Druck löse ich ein Ereignis aus. Da ich aber jetzt mit einer Navigationssoftware arbeite benötige ich wesentlich mehr Ressourcen, die wiederum andere Programmteile für einen kurzen Augenblick in der Hintergrund stellt.

Ohne die Threadprogrammierung werde ich wohl nicht mehr auskommen, oder seht ihr da andere Möglichkeiten!?

Wäre nett, wenn ich zu dem Thema noch ein paar Feedbacks erhalten könnte!

Gruss macke_a

B
101 Beiträge seit 2008
vor 15 Jahren

Wie ich weiter oben schon erwähnte, werden ja bei einem Prozessor, mit nur einem Kern, selbst bei der Thread-Programmierung alle Prozesse in einer Warteschleife gelegt. Nur für den Benutzter allein sieht es so aus, als würde der Prozessor mehrere Dinge gleichzeitig erledingen. D.h. stellt sich die Frage für was Threads denn wirklich sinnvoll erscheinen. Es gibt da eigentlich keine Rezept für. Aber von meiner Sicht aus sind Threads für Dinge wie: Telegramme erhalten, Clientanfragen - bei einem Server - erwarten, und so weiter.
Ein Thread ist letzenendes nur eine Abzweigung wo der Code sich nur für den Benutzter "trennt" und parallel läuft, meines erachtens (kann mich auch irren, solange code ich in C# noch nicht).

Einzige Ausnahmen sind Prozessoren mit mehr als einem Kern, denn die behandeln wirklich parallel mehrere Prozesse.

Ist es denn sinnvoll die Programmteile in mehrere Threads zu fassen?

Nein. Nur wenn es wirklich nötig ist ! Wenn du dir nicht sicher bist, dann lieber nachfragen.

Muss ich von Grund auf diese Beziehung einhalten?

Was für eine Beziehung meinst du ? Wenn sich das auf "alle Programmteile in Threads" bezieht, dann nein, weil siehe oben 😉

Ohne die Threadprogrammierung werde ich wohl nicht mehr auskommen, oder seht ihr da andere Möglichkeiten!?

Das kommt ganz auf die Situation an. Wenn du z.B. einen Server für einen Chat programmierst, der immer wieder damit beschäftig ist, Anfragen zu akzeptieren, dann würde es den Code natürlich aufhalten, denn die Methode Accept wartet bis eine Verbindungsanfrage gesendet wurde, vorher läuft der Code nicht weiter. So etwas Nicht in einem Thread abzulegen wäre fatal !

So gesehn brauchst du Threads, nur für Dinge, die deinen restlichen Code einfrieren würden.

mfg
bluedragon

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo macke_a,

so wie ich das sehe, steht alles was du wissen musst in [FAQ] Warum blockiert mein GUI? und [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke).

herbivore

M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren

Danke für die Beiträge und die Links von Euch. Ich möchte trotzdem noch einmal darlegen, wie ich meine Programmierung aufgebaut habe.


using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ThreadStarten
{
    static class Program
    {
        [MTAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
    }
} 

Alle meine Steuerelemente und das starten der Navigationssoftware befinden sich im Form1. Bis jetzt habe ich auf das einbinden von Control.Invoke bei Steuerelementen, außer bei einem Delegate-Aufruf verzichtet.

Der erste Weg zur Verbesserung meiner Software wäre vermutlich, dass das Starten der Navigationssoftware (navi.exe - Anwendung) außerhalb meiner Form1. Richtig?
Diesen Teil müsste ich demnach in meinem mitgelieferten Programmteil als zweiten Thread starten.

Der zweite Schritt wäre, den Aufruf Control.InvokeRequired bei meinen Steuerelementen mit einzubinden.

Das musste doch ein richtiger Anfang sein, oder?

Gruss macke_a

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo macke_a,

klingt gut.

herbivore

M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren

Ich habe die Veränderungen in meinem Quelltext vorgenommen und es ergeben sich deutliche Verbesserungen!!!

Es gibt aber noch eine Sache, da benötige ich noch einmal einen kleinen Denkanstoß.

Ich habe einen Thread definiert und benötige deren Funktion mehrfach um ein Routing zu starten.

public Thread ApiC = new Thread(new ThreadStart(ThreadC));
public void ThreadC() { /* starte Routing */ }

Dieser Thread wird gestartet , wenn ich eine Route berechne mit

ApiC.Start(); 

in meinem Programm.

Jetzt nutze ich den selben Thread, bei neuen Koordinaten um ein anderes Ziel zu routen, wieder.

Das Problem ist aber, eigentlich musste ich den Thread beenden und wieder von neuem starten. Das erscheint mir aber nicht als sinnvolle Lösung!

Was gibt es denn für Programmiermöglichkeiten wenn ein Thread mehrfach, aber mit unterschiedlichen Parametern genutzt werden soll?

Gruss macke_a

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo macke_a,

verwende eine synchronisierte Queue (Applikation mit Warteschlange) in die der Auftraggeber seine Aufträge einstellt und der Thread sie rausholt und abarbeitet.

herbivore

M
macke_a Themenstarter:in
291 Beiträge seit 2007
vor 15 Jahren

Danke für den Beitrag...

Wäre es nicht sinnvoller eine asynchrone Abarbeitung der Threads durchzuführen?
Ich lasse maximal eine Route berechnen und sobald eine neuer Zielort kommt, wird der alte Route gelöscht.

Gibt es denn nicht eine andere Lösung, außer die "Applikation mit der Warteschlange" ??

Besteht denn nicht die Möglichkeit, den Thread zu beenden und diesen anschließend wieder zu starten bzw. diesen mit neuen Daten zu versorgen?

Gruss macke_a

B
101 Beiträge seit 2008
vor 15 Jahren

Hallo macke_a,

einen Thread beenden kannst du mit Thread.Suspend(), ist jedoch veraltet.

Aber hier mal ein Beispiel wie du dne Thread indirekt immer neu mit Daten füttern könntest.


class Program
class Program
{
    private static string m_info = "hallo";
    private static string m_info2 = "tschüss";
    
    static void Main(string[] args)
    {
        Thread t = new Thread(new ThreadStart(rekursiv));
        t.Start();
        Thread.Sleep(1000); //lässt den Hauptprozess einschlafen, was eigentlich nicht so günstig ist, aber der Thread t läuft weiter
        m_info = "neee";
        m_info2 = "doch !";
        Thread.Sleep(1000);

        Console.ReadLine();

    }

    private static void rekursiv()
    {
        string info;
        string info2;
        int i = 0;
        for (int j = 0; j < 10; j++ )
        {
            info = m_info;
            info2 = m_info2;
            if (i == 0)
            {
                Console.WriteLine(info);
                i = 1;
            }
            else
            {
                Console.WriteLine(info2);
                i = 0;
            }
            Thread.Sleep(200); //lässt nur diesen Thread 200 Millisekunden schlafen
        }
    }
}


Ausgabe:

hallo
tschüss
hallo
tschüss
hallo
neee
doch
neee
doch
neee

Ich weiß nicht ob es vielleicht rekursive Threads gibts. Aber Sinn machen würden es auch keinen, da man einen Thread mit keine Paramtern versehen kann.

mfg bluedragon

Man muss viel gelernt haben, um nach etwas, worüber man nicht Bescheid weiß, richtig fragen zu können.

Wenn du jemandem vertrauen kannst, erübrigt sich ein Vertrag. Kannst du ihm nicht vertrauen, ist ein Vertrag nutzlos.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo macke_a,

Wäre es nicht sinnvoller eine asynchrone Abarbeitung der Threads durchzuführen?

der Thread läuft ja asynchron.

Gibt es denn nicht eine andere Lösung, außer die "Applikation mit der Warteschlange" ??

Es gibt immer viele Lösungen. Aber ich wüsste nicht, warum diese nicht auf deine Anforderung passen sollte.

Ich lasse maximal eine Route berechnen und sobald eine neuer Zielort kommt, wird der alte Route gelöscht.

Du kannst es ja trotzdem so programmieren, dass du die laufende Aktion abbrechen kannst.

Besteht denn nicht die Möglichkeit, den Thread zu beenden und diesen anschließend wieder zu starten bzw. diesen mit neuen Daten zu versorgen?

Nein!

herbivore