Jump to content

[C#]([Java]) TimeoutException ID2 und ID4


Recommended Posts

Hallo,

 

ich nutze einen Stack aus PowerSupply - Master - WiFi.

 

Mein Programm ist so aufgebaut, dass ich zyklisch die WiFi-Verbindung prüfe. Wenn eine Verbindung besteht, dann rufe ich die Connect-Methode der IPConnection auf. Vorher habe ich die IPConnection und sämtliche Bricklets instanziert.

 

Wenn nun ein Connect erfolgreich ist, erstelle ich ein Master-Objekt und frage den StackCurrent ab (just for fun). Das erfolgt also zyklisch.

:o Hier kommt es ab und zu zu einer TimeoutException mit ID2.

 

Weiterhin erfolgt nach erfolgreichen Connect, eine Meldung an sämtliche Bricklets (gekapselt in speziellen Klassen), wodurch diese initialisiert werden. Seltsamerweise funktioniert der Aufruf SetPortConfiguration des IO16 ohne Probleme.

>:( Wenn dann aber später im Programm ein GetPort oder SetPort aufgerufen wird, erfolgt regelmäßig eine TimeoutException mit ID2.

 

Nach einer halben durchzechten Nacht, habe ich aus Zufall ein neues Bricklet-Objekt vor dem Aufruf der GetPort-Methode erzeugt und dann auf diesem Objekt zusätzlich ein GetPort ausgeführt. Das funktionierte, also hab ich umgestellt und vor jedem Aufruf einer API-Methode erstelle ich nun ein neues Objekt des Bricklets. Sinnfrei aber funktioniert. In einer relativ zeitkritischen Software ist das aber kein dauerhafter Zustand.

 

Hier mal der vereinfachte (Exception-Handling weggelassen und andere nicht hilfreiche Logik) Ursprungscode:

 

private BrickletIO16 bricklet;

 

void InitBricklet(IPConnection ipCon) {

  if(isConnected) {

    bricklet = new BrickletIO16(brickletID, ipCon);

  }

}

 

float GetResistance(int channel) {

  if(isConnected) {   

    byte ports = bricklet.GetPort(bench); // Bang: Timeout // bench = 'B'

    // Hier Umformung des bytes ports, um diverse Ports zu setzen

    bricklet.SetPort(ports);

    float utest = testVoltageBricklet.GetVoltage() / 1000;

    return utest / 0.075f;

  }

}

 

So funktioniert es dann:

 

float GetResistance(int channel) {

  if(isConnected) {

    BrickletIO16 bricklet = new BrickletIO16(brickletId, ipCon);   

    byte ports = bricklet.GetPort(bench); // bench = 'B'

    // Hier Umformung des bytes ports, um diverse Ports zu setzen

    bricklet.SetPort(ports);

    float utest = testVoltageBricklet.GetVoltage() / 1000;

    return utest / 0.075f;

  }

}

 

Nur warum muss ich jedesmal ein neues Objekt erstellen, damit ich mit TF kommunizieren kann? Find das nicht besonders sauber, da die Zeit zum Erstellen eines Objekts relativ lang ist und ich schon zeit verliere fürs Exception-Handling. Das werde ich aber in naher Zukunft noch weg-optimieren.

 

Beste Grüße

Jörg

 

P.S.: War kurz davor TF aus den Fenster zu werfen, wenn nicht der Zufall gewesen wäre, den o.g. weg zu Testen...

Link zu diesem Kommentar
Share on other sites

Kannst du das Problem auf ein Beispielprogramm runterbrechen welches wir hier ausführen können?

 

Tritt das Problem auch auf wenn du keine WIFI Extension verwendest?

 

So richtig Sinn macht es nicht, der Konstruktur von der IO16 macht nicht mehr als ein paar Variablen zu initialisieren und sich selbst der IPConnection hinzuzufügen, so dass sie weiß wem die UID gehört.

Link zu diesem Kommentar
Share on other sites

Ich pack heut Abend mal die alte und neue Version und sende Euch das Projekt zu (VS2010 vorhanden?).

 

Ursprünglich habe ich das ganze auf Android entwickelt, aber als dann dort die Timeouts auftraten und eine .NET Testapp keine Probleme verursachte, habe ich das auf WPF umgestellt und mit einer sehr heißen Nadel gestrickt, denn ich brauche die Software und die Hardware am Wochenende einsatzbereit.

Link zu diesem Kommentar
Share on other sites

Ich habe mir dein Programm angesehen. Dein Problem mit dem IO-16 Bricklet liegt daran, dass du zwei BrickletIO16 Objekte für die gleich UID mit der gleichen IPConnection erzeugst.

 

Im MainWindow Konstruktor erzeugst du ein ControllerDevice mit UID gpL und ein ChannelDevice mit UID gpL. Beide leiten von Device ab und erzeugen dadurch zwei BrickletIO16 Objekte für die gleich UID.

 

Intern hält die IPConnection eine Tabelle, die UID auf Brick/Bricklet Objekt abbildet. Wenn du bei gleicher UID und IPConnection ein weiteres BrickletIO16 erzeugst, dann verdrängt das neu Objekt das alte aus dieser Tabelle. Der Effekt davon ist, dass Setter-Aufrufe auf dem alten BrickletIO16 Objekt noch funktionieren, die Antworten für Getter-Funktionen aber immer dem neuen BrickletIO16 Objekt zugestellt werden. Dadurch bekommst du einen Timeout beim Aufruf einer Getter-Funktion auf dem alten BrickletIO16 Objekt.

 

Das ist auch der Grund warum es hilft, wenn du das BrickletIO16 Objekt vor dem Getter-Aufruf neu erzeugst, weil diese dann das bisherige Objekt verdrängt und die Antworten zugestellt bekommt.

 

Wenn ich das richtig sehe, dann soll das ControllerDevice sich mit Port B und das ChannelDevice mit Port A eines IO-16 Bricklets befassen. Damit das klappt kannst du deiner Device Klasse beibringen, dass sich zwei Device Objekte ein BrickletIO16 Objekt teilen.

Link zu diesem Kommentar
Share on other sites

Ok, das erklärt einiges.

 

Obschon ich dann nochmal schauen muss, warum das in android auch so ist. Denn dort habe ich eine Device-Factory erstellt, wodurxh nur singletons geben dürfte. Der .net code ist nicht vollständig gleich, da ich aus Zeitgründen einen umbau von java auf .net einfach ein paar dinge unter den tisch kehren musste, um in der timeline zu bleiben.

 

Ich baue die factory ein und berichte über das Ergebnis.

 

Erstmal vielen dank.

 

Btw: bei überschreiben von objekten in einer liste wäre ein hinweis gut. Evtl. Sogar exception wie AlreadyAttachedException oder so.

Link zu diesem Kommentar
Share on other sites

Das aktuelle Verhalten beim Überschreiben von Objekten können wir nicht so einfach ändern, da sich existierende Programme darauf verlassen könnten.

 

Was wir aber machen können ist beim Aufruf von Gettern eines überschriebenen Objekts eine spezielle IchWurdeÜberschriebenException zu verwenden, statt einer TimeoutException. Dann ist dies leichter zu erkennen.

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...