Wie führe ich eine Methode in einem anderen Thread aus?

9

Ich suche nach einer Lösung für dieses Problem in C oder C ++.
Bearbeiten : Um zu klären. Dies ist auf einem Linux-System. Linux-spezifische Lösungen sind absolut in Ordnung. Cross-Plattform ist kein Problem.

Ich habe einen Dienst, der in einem eigenen Thread läuft. Dieser Dienst ist eine Klasse mit mehreren Methoden, von denen einige im Thread des eigenen Dienstes und nicht im Thread des Aufrufers ausgeführt werden müssen.

Gegenwärtig verwende ich Wrapper-Methoden, die eine Struktur mit Eingabe- und Ausgabeparametern erstellen, die Struktur in eine Warteschlange einfügen und entweder zurückkehren (wenn ein "Befehl" asynchron ist) oder auf ihre Ausführung warten (wenn ein "Befehl" ist) synchron).

Auf der Thread-Seite wird der Dienst aktiviert, eine Struktur aus der Warteschlange wird geöffnet, es wird herausgefunden, was ausgeführt werden soll, und die entsprechende Methode wird aufgerufen.

Diese Implementierung funktioniert, aber das Hinzufügen neuer Methoden ist ziemlich umständlich: Definieren Sie Wrapper, Struktur mit Parametern und Handler. Ich habe mich gefragt, ob es ein einfacheres Mittel gibt, diese Art von Modell zu codieren: eine Klassenmethode, die auf dem eigenen Thread der Klasse statt im Thread des Aufrufers ausgeführt wird.

bearbeiten - Art der Schlussfolgerung:
Es scheint, dass es keinen de facto Weg gibt, das zu implementieren, was ich gefragt habe, was keinen zusätzlichen Programmieraufwand erfordert Ich bleibe bei dem, was ich herausgefunden habe, es gewährleistet Typensicherheit, minimiert das Sperren, ermöglicht Sync- und Async-Aufrufe und den Overhead ziemlich bescheiden Auf der anderen Seite erfordert es ein wenig extra Codierung und der Versandmechanismus kann aufgebläht werden, wenn die Anzahl der Methoden zunimmt. Wenn Sie die Dispatch-Methoden für die Konstruktion registrieren oder die Wrapper diese Aufgabe ausführen, scheint das Problem zu lösen, ein wenig Overhead zu entfernen und auch etwas Code zu entfernen.

    
amso 24.11.2010, 16:31
quelle

5 Antworten

1

Je nach der Komplexität, die Sie akzeptieren möchten, gibt es mehrere Möglichkeiten, dies zu erreichen. Die Komplexität des Codes ist direkt proportional zur gewünschten Flexibilität. Hier ist eine einfache (und ziemlich gut verwendet):

Definieren Sie eine Klasse, die jeder Funktionalität entspricht, die Ihr Server bereitstellt. Jede dieser Klassen implementiert eine Funktion namens execute und nimmt eine Grundstruktur namens input args und output args.

Innerhalb des Dienstes registrieren Sie diese Methodenklassen zum Zeitpunkt der Initialisierung. Sobald eine Anfrage an den Thread kommt, hat sie nur zwei Argumente, Input und Ouput, welche die Basisklassen für spezialisiertere Argumente sind, die von verschiedenen Methodenklassen benötigt werden.

Dann schreiben Sie Ihre Serviceklasse als reine Delegierung, die die eingehende Anfrage übernimmt und basierend auf der ID oder dem Namen der Methode (die bei der ersten Registrierung verwendet wurde) an die entsprechende Methodenklasse weiterleitet.

Ich hoffe, dass es Sinn macht, ein sehr gutes Beispiel für diesen Ansatz ist in der XmlRpc ++ (eine C ++ - Implementierung von XmlRpc, können Sie den Quellcode von Sourceforge erhalten).

Zur Erinnerung:

%Vor%

Sie werden immer noch den Warteschlangenmechanismus verwenden, aber Sie werden keine Wrapper benötigen.

    
Rajivji 24.11.2010, 16:51
quelle
2

Meine Standardreferenz für dieses Problem ist hier .

  

Implementieren einer Thread-sicheren Warteschlange mithilfe von Bedingungsvariablen

Wie @John bemerkt, verwendet dies Boost.Thread.

Ich würde bei dem hier beschriebenen synchronen Fall vorsichtig sein. Es ist leicht, Perf-Probleme zu bekommen, wenn der Producer (der sendende Thread) auf ein Ergebnis vom Consumer (dem Service-Thread) wartet. Was passiert, wenn Sie 1000 Async-Aufrufe erhalten, die Warteschlange mit einem Rückstand füllen, gefolgt von einem Synchronisierungsaufruf von jedem Ihrer Producer-Threads? Ihr System wird "tot" spielen, bis der Warteschlangen-Backlog gelöscht wird, wodurch diese Synchronisierungs-Caller frei werden. Versuchen Sie, sie nur mit Async zu entkoppeln, wenn Sie können.

    
Steve Townsend 24.11.2010 16:38
quelle
1

IMHO, wenn Sie Methodenausführung und Threadkontext entkoppeln möchten, sollten Sie Active Object Pattern (AOP)

verwenden

Sie müssen jedoch ACE Framework verwenden, das viele Betriebssysteme unterstützt, z. Windows, Linux, VxWorks

Hier finden Sie detaillierte Informationen

Außerdem ist AOP eine Kombination aus Befehls-, Proxy- und Beobachtermustern. Wenn Sie die Details kennen, können Sie Ihr eigenes AOP implementieren. Hoffe es hilft

    
baris.aydinoz 25.11.2010 13:44
quelle
0

Zusätzlich zur Verwendung von Boost.Thread würde ich boost :: function und boost :: bind betrachten. Dennoch scheint es fair zu sein, untypped (void) Argumente an die Zielmethoden zu übergeben und diese Methoden in den richtigen Typ zu konvertieren (ein typisches Idiom für Sprachen wie C #).

    
Brent Arias 24.11.2010 16:58
quelle
0

Hey Rajivji, ich denke du hast es auf den Kopf gestellt. Die Komplexität des Codes ist umgekehrt proportional zur Flexibilität. Je komplexer Ihre Datenstrukturen und Algorithmen sind, desto mehr Einschränkungen setzen Sie auf akzeptable Eingaben und Verhalten.

Zum OP: Ihre Beschreibung scheint vollkommen allgemein und die einzige Lösung, obwohl es verschiedene Kodierungen davon gibt. Am einfachsten kann man eine Klasse von:

ableiten %Vor%

und dann eine thread-sichere Warteschlange von Zeigern zu Xqt. Der Dienst-Thread öffnet dann die Warteschlange nur für px und ruft px- & gt; xqt () auf, und löscht dann px. Die wichtigste abgeleitete Klasse ist diese:

%Vor%

weil "alle Probleme in der Informatik durch eine weitere Ebene der Indirektion gelöst werden können" und insbesondere löscht diese Klasse den Delegierten nicht. Dies ist viel besser, als wenn beispielsweise ein Flag verwendet wird, um zu bestimmen, ob das Closure-Objekt vom Server-Thread gelöscht werden soll.

    
Yttrill 24.11.2010 22:25
quelle