Eventhandler "Queued" ausführen



  • Hallo zusammen,

    von Qt her kenne ich das so, dass wenn ich ein objekt in einem Hintergrundthread habe und ein Signal davon mit einem Slot eines Objekts in dem Hauptthread verbinde, dass wenn ich das Signal dann emitte, der Aufruf des Slots zunächst auf eine Queue gepackt wird und dann vom Haupthread später aufgerufen wird.
    Das ganze nennt sich Qt::QueuedConnection.

    Geht das bei C# mit Windows Forms auch so, oder muss ich das anders machen?

    Konkret geht es um einen Webservice. Ich will den Webservice asynchron aufrufen. Im CompletionHandler, der asynchron aufgerufen wird, will ich dann ein anderes Event auslösen und der Handler zu diesem Event soll dann später synchron vom Haupthread aufgerufen werden.
    Geht das irgendwie?

    Ich weiß, dass es BeginInvoke / EndInvoke und bei Windows Forms auch Invoke gibt, aber ich glaube das ist nicht ganz das, was ich suche.

    Könnt ihr mir weiterhelfen?

    Falls es keine direkte Entsprechung gibt: Wie würdet ihr das bei Windows Forms dann lösen/umsetzen?





  • Hallo.

    BeginInvoke und Invoke ist das, was Dir zur Verfügung steht, um Code in den Gui-Thread zu verlagern.

    Invoke ist blockierend, also synchron. BeginInvoke asychron. BeginInvoke behält aber auch eine Queue an anstehenden Arbeitsaufträgen vor, die Schritt für Schritt abgearbeitet werden, auch wenn das Ganze durchaus mit mehreren Sekunden Verzögerung passieren kann. (Bei großer Anzahl an Aufträgen)

    Du schreibst zweimal davon, dass etwas "später" durchgeführt werden soll. Was meinst Du genau damit?

    Evtl. ist dein Ansatz im Hintergrundthread nicht ganz das was Du suchst.
    Mir spinnt etwas wie eine Producer-Consumer-Queue im Kopf herum. Die hat am Ende auch einen BeginInvoke/Invoke-Call bei der Verlagerung der Ergebnisse in den GUI-Thread, aber die eigentliche Abarbeitung der Arbeitsaufträge ist evtl. der Knackpunkt deines Problems.

    Insofern: Bitte mehr Info 🙂



  • Also was ich eigentlich erreichen will, ist in einem Hintergrundthread etwas übers internet zu empfnagen und dieses empfangene dann im gui-thread zu verarbeiten.

    Ich würde das gerne irgendwie so hinbiegen, dass die Klasse, die für das Empfangen zuständig ist ein event anbietet und die methoden, die als EventHandler geadded werden dann vom GUI-thread aufgerufen werden.

    Mit später war gemeint, dass der GUI-Thread ja evtl. gerade etwas anderes abarbeitet und sobald er Zeit hat er dann das event behandeln kann.

    Ist da dann BeginInvoke das richtige oder vielleicht der BackgroundWorker?
    Es ist aber nicht so, dass das ein Task ist, der im Hintergrund ausgeführt ist und irgendwann fertig ist. Sondern es soll periodisch nach neuen Daten geguckt werden. Das eigentliche nachgukcne sollte aber asynchron passieren (was auch kein Problem ist, dafür gibtgs bei .net webservices entsprechende methoden), weil das Aufrufen eines Webservices evtl. ein bischen dauern kann.

    Ich hatte mal gelesen, dass BeginInvoke mit einem Threadpool arbeitet und das wäre ja für GUI falsch. ODer ist das, wenn ich das auf einem Form element aufrufe anders?
    Ein Problem ist dann aber auch, dass ich in der betreffenden Klasse eigentlich gar keine Referenz auf ein Form Element habe.



  • BackgroundWorker passt da eher nicht so.

    Dein Ansatz mit dem event sieht schon richtig aus. Die Form abonniert das event womit der Worker keine Referenz auf die Form benötigt). Innerhalb des Eventhandlers (in der Form) rufst Du this.BeginInvoke auf um den Code asynchron an den GUI-Thread zu delegieren. Der Worker kann dann weitermachen und die GUI wird Zeitnah den Auftrag abarbeiten.

    Dieser Ansatz kann dann scheitern, wenn der Worker-Thread die Gui mit Aufträgen bombadiert. Dann ist sammeln der Aufträge und Abarbeitung größerer Mengen solcher vielleicht ein besserer Ansatz. D.h. nur jedes x-te Event in den Gui-Thread wechseln und die zwischenzeitigen Aufträge auf einen Schlag ausführen.



  • Danke für die Hilfe!

    Ich werd das dann so machen.
    Mit Bombadieren sollte da eigentlich nichts sein, so nen event kommt vielleicht alle paar sekunden einmal, mehr nicht.

    Wenn ich schonmal dabei bin... vielleicht kennt ihr euch ja auch ein bischen mit webservices aus, mir gehts ja speziell um .NET, deswegen ist die sektion hier vielleicht gar nicht so falsch.

    Ich will einen Webservice schreiben, der u.A. von der Anwendung benutzt wird, um einen Chat zwischen verschiedenen benutzern anzubieten.
    Jetzt könnte man einfach alle paar sekunden (z.B. mit einem Timer) gucken, ob neue Nachrichten da sind.
    Das wird vermutlich auch funktionieren, hat aber 2 Nachteile: 1. Verzögerung, 2. mehr Kommunikation mit dem Server, als nötig.

    Ich hab dann mal ein bischen was zu asynchronen Webservices gelesen.
    Die Idee ist es einen Webservice asynchron aufzurufen. Der eigentliche Aufruf (der asynchron durchgeführt wird), blockiert dann beim server solange, bis neue Nachrichten da sind und kehrt erst dann zurück. Und falls zulange nichts kommt kann der aufruf auch timouten und dann z.B. null oder ähnliches zurückgeben.

    Eigentlich hört sich das gut an und ist vermutlich auch nicht schwer zu implementieren (einfach ne wait condition benutzen).
    Allerdings habe ich bedenken, das ich Probleme kriege, weil die Anzahl der Threads eines Webservices soweit ich weiß begrenzt ist.

    Wenn ich jetzt für jeden Benutzer einen eigenen Thread starte, der solange blockiert, bis etwas neues da ist, dann könnte es ja passsieren, dass irgendwann keine neuen anfragen mehr angenommen werden, weil alle threads, die den webservice vom server aus bedienen vergeben sind. Ist das so, oder ist die Sorge unberechtigt?

    Kennt ihr noch andere Alternativen?



  • Der Server sollte keine Threads blockieren und das ist auch nicht notwendig.

    Ein Programmablauf kann warten ohne dass ein Thread aus dem Pool blockiert wird, wie es bei Sleep oder synchroner Kommunikation der Fall wäre. NET bietet dafür Dinge wie Monitor (Pulse,Wait) und WaitHandles.

    Außerdem kann der Server selbst asynchron kommunizieren. Neue Nachrichten werden dabei in Threads aus dem Threadpool und innerhalb von entsprechenden Events abgearbeitet.

    Mit solchen Sachen kann ein kleiner Server locker 1000 Clients bedienen, während er bei 100 normalen Threads schon an sein Limit kommen würde.

    (Mit Webservices speziell kenne ich mich nicht aus. Nur mit Sockets und dergleichen.)



  • µ schrieb:

    Ein Programmablauf kann warten ohne dass ein Thread aus dem Pool blockiert wird, wie es bei Sleep oder synchroner Kommunikation der Fall wäre. NET bietet dafür Dinge wie Monitor (Pulse,Wait) und WaitHandles.

    Monitor Pulse/Wait meinte ich ja mit Waitcondition. Nur führt das nicht zu genau dem gleichen wie ein normaler sleep? Der Thread wird doch solange pausiert, bis jemand anders Pulse aufruft.

    µ schrieb:

    Außerdem kann der Server selbst asynchron kommunizieren. Neue Nachrichten werden dabei in Threads aus dem Threadpool und innerhalb von entsprechenden Events abgearbeitet.

    Meinst du, der server kann aktiv nachrichten zum client senden, ohne eine Anfrage?
    Ich glaub eigentlich nicht, dass das bei webservices möglich ist.

    Was für andere arten von server-technologie könnte ich denn benutzen?



  • Vergiss den letzten Beitrag. Ich war mit den Gedanken bei einem anderen Problem.
    Zum Thema Webservices lasse ich anderen den Vortritt.



  • Ok, ich werd die frage zum webservice dann nochmal unter webzeugs posten.
    Falls es noch probleme mit den Eventhandlern gibt, melde ich mich hier nochmal.


Anmelden zum Antworten