Synchronisieren des Zugriffs auf Subs und Funktionen (Thread und Userzugriff)

  • VB.NET

Es gibt 34 Antworten in diesem Thema. Der letzte Beitrag () ist von metzelmax.

    Hallo Rod,

    Naja, wenn ich hunger hab guck ich unter Umständen schon mal wo der Bote bleibt;). Aber zum Thema:

    Also prinzipiell erben alle Geräteklassen von einer gemeinsamen Basis. Jedes Gerät besitzt auch eine eigene Klasse und wird über die jeweilige Klasseninstanz angesprochen.
    Das Datarecive ist prinzipell ne feine Sache wenn man weiß woher ne Anfrage kam. Wenn ich aber verschiedene Threads habe welche unterschiedliche Befehle über die Schnittstelle schicken und entsprechende Antworten erwarten kommt man sicher durcheinander. Vor allem wenn es eine Bus-Schnittstelle mit mehreren Geräten ist.
    Ich bin natürlich immer offen für Verbesserungsvorschläge, hier steh ich dann allerdings auf der Leitung. Beim Bus macht das Datarecive doch eigentlich keinen Sinn da ich ja nur Senden oder empfangen kann über die Rs485 möglich ist (halbduplex). Dein vorschlag klingt aber interessant. Hast du vielleicht genauere Infos zu einem solchen vorgehen mit dem Recive und einer List für meinen Fall? Kann man so was auch verwenden wenn ich mit dem Thread Funktion 1 und der User Funktion 2 aufrufen welche beide Senden und Empfangen wollen?

    metzelmax schrieb:

    wenn man weiß woher ne Anfrage kam.
    Ja das weißt Du doch, oder schickst Du auf Port3 eine Anfrage und empfängst auf Port7 die Antwort?
    Und bei den Multi-Geräten: Du schickst doch die Anfrage mit ID und bekommst in der Antwort die ID zurück. @ErfinderDesRades:: Jou, so isses, zumindest sollte es so sein.
    Wenn das nun so ist, hast Du einen riesigen Overhead.
    Wenn das aber nicht so ist, schick den Kram an die Hardware-Leute zurück und lass sie es so machen.
    Also:
    Wie isses nun?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo

    Ja, es stimmt schon das ich die ID mitgeschickt bekomme. Allerdings habe ich 3 Geräte mit Ascii-Übertragung und eines mit Bytes (ModBus). Bei reinem Ascii hätte ich mich vielleicht schon ran getraut aber bei so nem misch-masch hatte ich Berührungsängste... ;) . Aber nochmal zum empfang selbst:

    Wenn ich ein Gerät z.B. auf Port1 habe und ich ne Anfrage sende (z.B. Gib_Temperatur), der Thread aber kurze Zeit davor oder später (weil ja synclock) eine andere Anfrage schickt (z.B. Gib_Spannung), dann erwarte ich ja zwei antworten auf dieser Schnittstelle. Wie kann man das denn praktisch verwalten, damit man die jeweiligen Antworten richtig zuordent. Gibt es eine möglichkeit so was wie ein First In First Out zu realisieren?

    Schwieriger stelle ich mir das ganze bei der Bus-Schnittstelle vor. Hier könnten ja praktisch bis zu 8 Anfragen nahezu zur selben Zeit über die Schnittstelle haschen und ich müsste die dann effektiv und richtig zuordnen (User und Thread je Gerät). Dank der ID Wäre zumindest die Zuordnung des Geräts möglich, jedoch steht man dann auch vor dem obigen Problem. Ach ja... Ich trau mich fast nicht zu fragen... Wie kann ich eigentlich verschiedene Datentypen bei z.B. einer Funktion zurückgeben (z.B. String, Integer,Double je nach anfrage).

    Ich werde jetzt mal versuchen meine Basisklasse nach Rods Vorschlag zu modifizieren, also ein Datarecive einzubauen. Ich befürchte das ich da noch auf so manches Problem stoßen werde, hoffe Ihr helft mir da ein bissl :rolleyes:

    metzelmax schrieb:

    Wie kann ich eigentlich verschiedene Datentypen bei z.B. einer Funktion zurückgeben (z.B. String, Integer,Double je nach anfrage).
    Deine Herangehensweise ist falsch.
    Ich hab Dir ein bei mir funktionierendes Modell vorgestellt.
    Du hast nun aus meiner Sicht folgende 2 Möglichkeiten:
    Du stellst Dein Projekt um bzw. Du schreibst den Kommunikations-Teil Deines Projekt völlig neu, dabei kannst Du auf meine Hilfe rechnen.
    Oder
    Du wurstelst weiter in Deinem Spagettihaufen rum und suchst den anderen Zipfel der Wurst, dabei werde ich Dir nicht helfen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Erfinder:

    Vielen Dank für die klare und kurze Antwort. Dann brauch ich danach zunächst nicht zu suchen. Eventuell gibt es ja andere Mittel und Wege so was zu realisieren aber das ist dann doch etwas fernab vom Thema;).

    @Rod:

    Ja, ich dachte mir schon das das auf wenig Gegenliebe stößt;). Nun aber zu deinem Modell. Ich werde versuchen meine Kommunikation entsprechend deines Vorschlags umzustellen. Ist an sich nicht schwer da ja alle Geräte von einer Basisklasse erben. Jetzt muss ich aber grübeln wie ich das mit der Rückgabe gestalten kann. Insbesondere wenn ich mehrere Geräte habe.

    Ich versuch mal meinen "Gedankenknoten" zu skizzieren:

    Ich habe eine Basisklasse, welche den Seriellen Port sowie verschiedene Grundfunktionen beinhaltet. Zudem befindet sich darin eine Send-Funktion, der ich befehle an das jeweilige Gerät übergebe und die Antwort zurück gegeben bekomme. Möchte ich also von verschiedenen Geräten Daten erhalten, geht das der Reihe nach und ich bekomme meine Antworten entsprechen. Nachteil: Der Port wird solang geblockt bis die Daten angekommen sind oder ein Timeout einsetzt.

    Nun würde ich das Event des Ports nutzen um beim Eintreffen von Daten diese Einlesen zu können. Das Event sollte sich ja immer dann melden, wenn irgendwas im Empfangspuffer hängt. Dabei ist es allerdings egal, welches Gerät die Anfrage gesendet hat. Gibts nur eine Schnittstelle pro Gerät kann man die Antwort leicht zuordnen. Gibt es mehrere ginge dies, wie du bereits erwähntest, per ID. Ich könnte also im Event des Shared Ports für die Bus-Schnittstelle ein
    Select case für die ID einbauen und die Antwort versuchen entsprechend
    auszuwerten. Allerdings müsste man im Anschluss daran wissen, welche Anfrage gesendet wurde um die Antwort entsprechend zuordnen zu können. Hast du eventuell einen Hinweis wie man das am besten anstellen kann?

    Folgendes Konstrukt:

    Gerät A, B und C hängen an COM1. Die Geräte werden permanent abgefragt und geben ihre Antwort entsprechend zurück. Im Recive-Event packe ich das Select Case für ID_A, ID_B und ID_C rein um die Antwort zuordnen zu können. Sollte ich die Antwort erhalten haben wirds schwieriger. Da ich ja von der Basis erbe kann ich nicht in die Child-Klasse Daten übergeben, oder geht das doch? Wie übergebe ich die Daten? Per Property in der Basisklasse?

    metzelmax schrieb:

    Jetzt muss ich aber grübeln wie ich das mit der Rückgabe gestalten kann.
    Eine Instanz, ein Port, ein DataReceived-Event. Ein gesendete-Data-Member.
    Und wenn Du diese Klasse n Mal instanzierst, musst Du lediglich dafür Sorge tragen, dass jede Instanz ein anderes COM-Port zugewiesen bekommt.
    Kann es sein, dass Du von OOP keine klare Vorstellung hast?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sorry, war gestern verhindert.

    Eine Instanz, ein Port ist soweit vollkommen klar. Das funktioniert bei RS232 auch prima. Wenn ich aber nen Bus habe, verwendet jede Instanz ein und denselben port und greift demzufolge auch auf das gleiche Datarecive-Event zu. Daher hab ich auch ein Verständnisproblem... Wenn ich jeder instanz einen eigenen Port zuweisen würde behandelt VB die sicher wie eigenständige Geräte aber hardwaremäßig hängen die alle zusammen und teilen sich die verfügbare Schnittstelle. Oder liegt hier auch ein Denkfehler?

    Was sicher möglich wäre, in jeder Instanz eines Bus-Geräts ein Datarecive zu packen. Dann hätte man aber u.u. redundanten Code... Ich steh also weiterhin ein bissl auf der Leitung...:/... Obwohl, wenn ich so recht drüber nachdenke... Ich kann ja anhand der ID prüfen für welches Gerät die Nachricht sein soll. Dann benötige ich in jeder Klasseninstanz ein eigenes Datarecive in welchem ich die Nachrichten einlese und nach überprüfen der ID entsprechend verwerfe oder weiterverarbeite... Ich werd mal ausprobieren ob ich es irgendwie hin bekomme zumindest im Datarecive die Antworten zu erhalten. Wie ich die dann aber zuordnen muss weiß ich noch nicht....

    metzelmax schrieb:

    Wenn ich aber nen Bus habe
    bekommt dieses Arrangement eine eigene separate Klasse, hatten wir schon.
    Wie unterscheidet Dein Programm die an diesem einen Port hängenden n Geräte?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Im Programm selbst erzeuge ich die Geräteinstanzen welchen ich beliebige Namen zuteile:

    Private withevents MyGerätA as new GerätA(Port,ID)
    Private withevents MYGerätB as new GerätA(Port,ID)
    ... usw.

    Ich nutzte dann die Methoden und Funktionen der Instanzen um mit den Geräten zu kommunizieren bzw. nutze deren Events. Da ich den Empfang derzeit beim Bus immer noch so geregelt habe, das blockierend gesendet und empfangen wird, ist eine weitere Unterscheidung nicht notwendig. Antwortet ein Gerät nicht oder kommt es zum Timeout wird eine entsprechende Exception erzeugt und als Fehlerevent des Geräts ausgegeben. Antwortet das Gerät ordnungsgemäß, wird die Antwort als Rückgabewert der Sendefunktion weiterverarbeitet. Nachteil wäre hierbei eventuell die längere Dauer bei Übertragungsfehlern, da die Schnittstelle bis zum Timeout des Geräts geblockt wird.

    metzelmax schrieb:

    welchen ich beliebige Namen zuteile:
    Woher weiß das Gerät, dass Du mit ihm kommunizierst?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ach so meinst du das. Naja in der Geräteklasse werden die Befehle an das jeweilige Gerät entsprechend zusammengebaut. Je nach Gerät kommt die ID oder ein Steuerzeichen und die ID und danach der eigentliche Steuerbefehl. Das Gerät erkennt dann die ID und führt den Befehl entsprechend aus. Da wir aufm Bus sind kann auch nur dieses Gerät antworten.Im Bus dann wieder entsprechend mit ID.

    metzelmax schrieb:

    Ach so meinst du das.
    Du hast ein Problem, ich habe mich nur zur Hilfe angeboten.
    Also: Ich erwarte ein wenig mehr Kooperation von Dir.
    Ich habe keine Lust, Dir jede kleine Information aus der Nase zu ziehen.
    Und:
    Wenn das so ist, wie Du schreibst und so wie ich denke, brauchst Du keinerlei Restriktionen.
    In der Multi-Klasse solltest Du das Senden sperren, bis die Antwort da ist, das sollte reichen, sofern es ühaupt erforderlich ist.
    Den Rest mach so, wie isch es beschrieben habe.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sorry, hab dich vorhin nur nicht richtig verstanden;).

    Ah, die Sendefunktion zu sperren wäre sicher ne interessante Möglichkeit um das Recive-Event nutzen zu können. Da ja nur Halbduplex möglich ist wäre ohne sperre vermutlich die ankommende Nachricht im Nirvana weil das nächste Gerät bereits seine Befehle ballert obwohl das erste noch nicht seine Antwort beendet hat. So könnte man das umgehen. Ich sollte das mal testen ob das vorteile bei der Verarbeitung bringt. Hab da schon ne Idee...

    Ich würde mich dann nochmal melden wenn ich wieder ein paar konkretere Fragen habe. Danke erstmal für deine Hilfe Rod:)