2 Stimmen

Funktion wartet auf Antwort von anderer Anwendung

Wir arbeiten an der Integration von zwei verschiedenen Anwendungen, die gleichzeitig laufen und Daten austauschen. Eine Anwendung stellt die Daten zur Verfügung, die andere berechnet einige Werte auf der Grundlage von externen Systemen und den Daten und muss diese an die erste Anwendung zurückgeben.

Wir verwenden diese Bibliothek, um die Daten zwischen den Anwendungen auszutauschen: http://grouplab.cpsc.ucalgary.ca/cookbook/index.php/Toolkits/Networking

Die Bibliothek ermöglicht es im Grunde, ein gemeinsames Wörterbuch zu erstellen, das von jeder Anwendung abgefragt werden kann (solange sie den Ort des gemeinsamen Wörterbuchs kennt).

Was also passieren sollte, ist, dass Programm A Programm B einige Daten zur Verfügung stellt und Programm B diese Daten verwendet und andere Daten an Programm A zurückgibt.

Mein Problem ist, wie bringe ich das Programm A dazu, auf die Antwort von B zu warten. Konkret kann ich ein Objekt in das gemeinsame Wörterbuch aufnehmen, das andere Programm wird über eine Änderung im Wörterbuch benachrichtigt, es kann einige Attribute berechnen und das Objekt im Wörterbuch aktualisieren. Programm A kann benachrichtigt werden, aber ich möchte, dass Programm A wartet, bis es diese Antwort zurückerhält - die Aktion von Programm A sollte auf dem zurückgegebenen Wert basieren.

Eine sehr hässliche Art und Weise sehe ich dies getan werden kann, ist eine Endlosschleife innerhalb der Funktion, die hält Abfragen des Wörterbuchs, um zu sehen, wenn das Objekt udpated wurde - wenn es aus der Schleife zu brechen und verwenden Sie das Objekt und seine berechneten Attribute. Kennt jemand eine schönere Lösung?

2voto

Travis Gockel Punkte 25964

Unter Verwendung ihrer Abonnementmodell können Sie alle Endlosschleifen vermeiden. Warum sollten Sie eine Schleife machen, wenn Sie nur dann prüfen müssen, wenn etwas tatsächlich aktualisiert wird? Da Sie Schlüsselmuster im Wörterbuch abonnieren und Ihre Verbindung benachrichtigt wird, wenn ein zu diesem Muster passender Schlüssel aktualisiert/hinzugefügt wird, brauchen Sie nur dies zu überprüfen.

Im Grunde können Sie also ein ManualResetEvent verwenden, um auf die Synchronisierung innerhalb Ihres eigenen Systems zu warten. Hier ist ein Beispiel für die Verwendung von ManualResetEvent:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        //    create the reset event -- initially unsignalled
        var resetEvent = new ManualResetEvent(false);
        //    information will be filled by another thread
        string information = null;

        //    the other thread to run
        Action infoGet = delegate
        {
            //    get the information
            information = Console.ReadLine();
            //    signal the event because we're done
            resetEvent.Set();
        };

        //    call the action in a seperate thread
        infoGet.BeginInvoke(null, null);
        //    wait for completion
        resetEvent.WaitOne();
        //    write out the information
        Console.WriteLine(information);
    }
}

Um es auf Ihr Framework zu übertragen, könnten Sie den Subskriptionshandler prüfen lassen, was aktualisiert wurde, das Wartehandle finden und es signalisieren, um so die entsprechenden wartenden Threads voranzutreiben.

0 Stimmen

Vielen Dank für Ihre ausführliche Antwort. Ich denke, das würde bei mir funktionieren. Ich werde versuchen, es zu implementieren, um sicherzustellen, dass es funktioniert. Ich danke Ihnen!

1voto

Jimmy Punkte 85199

Ein ManualResetEvent verwenden.

 // machine A
 var event = new ManualResetEvent(false);
 B_Listener.OnChanged += delegate { event.Set(); }
 myDictionary.UpdateValue();
 event.WaitOne();

0 Stimmen

Interessant, ich habe das Gefühl, dass ich so etwas brauche. Ich werde mir die Anwendung genauer ansehen.

0voto

Michael Bray Punkte 14660

Ohne andere IPC-Methoden zu verwenden (da Sie sich auf diese spezielle Bibliothek festgelegt zu haben scheinen), scheint es mir, dass kontinuierliches Polling ungefähr die einzige Möglichkeit ist. Wenn Sie bereit (und in der Lage) sind, andere IPC-Methoden zu implementieren, dann sollten Sie die aktuelle Bibliothek nicht mehr verwenden und die Daten zwischen den Programmen einfach selbst weitergeben.

0 Stimmen

Der einzige Grund, warum ich diese Bibliothek verwende, ist, dass sie einfach zu verwenden scheint. Aber wenn es andere IPC-Methoden gibt, die besser funktionieren könnten, lassen Sie mich bitte wissen.

0voto

Jay Punkte 53725

Wenn ich es richtig verstehe, darf Programm A keine zusätzliche Logik ausführen, bis Programm B den Wert aktualisiert hat und Programm A eine Benachrichtigung über diese Aktualisierung von diesem System aus UCalgary erhalten kann.

Ausgehend von diesen Annahmen würde ich vorschlagen, dass Sie nach dem Senden von Daten an das gemeinsame Wörterbuch einen Timer starten, dessen Tick Ereignis wird von einer Methode behandelt, die entweder (a) das Wörterbuch auf Aktualisierungen prüft oder (b) eine Variable prüft, die durch die Benachrichtigung gesetzt wird, die von der gemeinsam genutzten Wörterbuchbibliothek eingeht.

Sobald die Aktualisierung gefunden wurde, stoppen Sie den Zeitgeber und führen die Methode aus, die die Verarbeitung des neu aktualisierten Wertes übernimmt.

Der Timer ist der von Ihnen vorgeschlagenen "Endlosschleife" nicht unähnlich, aber er hat praktisch keinen Verarbeitungsaufwand, kann so eingestellt werden, dass er in einem realistischen Intervall prüft (sei es 1 Sekunde, 1 Minute, 24 Stunden), und er kann so eingestellt werden, dass er ausläuft, wenn die Dinge mit Programm B oder dem Wörterbuch nicht wie geplant laufen.

0 Stimmen

Stimmt, aber es ändert die Codestruktur auf eine seltsame Weise, wie ich finde. Da alles, was Programm B nach dem Erhalt der Aktualisierung von Programm A zu tun hatte, nun in eine andere Funktion verschoben werden muss, die vom Tick_event-Handler aufgerufen wird, anstatt so etwas wie dies: int a = getResponseFromB(key); if (a == 1) ... . Im Fall des Tickens würde der Code meiner Meinung nach etwa so aussehen: getResponseFromB(key); //Function ends here} gefolgt von public void AnotherFunction(a) { ... } die vom Tick-Ereignishandler aufgerufen wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X