Thread-sicheres Feuern von Events

  • C#
  • .NET (FX) 4.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Thread-sicheres Feuern von Events

    Hey Leute,

    schnell zur Sache, ich hab ein Netzwerkmodul, dass sich auf 2 Wegen zu einem Server verbindet. Wieso 2? damit ich einen Fallback habe, falls Firewalls etc. nicht gelockert werden können. Das tut aber nichts zur Sache. Über weg Nummer 1 erledige ich alles bequem per Async Funktionen der Socket Klasse. Weg Nummer zwei hat diese Funktionen nicht, da ich aber nicht möchte, dass alles Einriert (bis zu 15 Sekunden), bleibt nur ein Weg übrig, ich implementiere den Async-Part slebst. Wie? Ich packe die Kommunikation innen Thread(-Pool) und feuere ein Event, wenns Fertig ist. Das ist soweit nicht das schwere. Mein Problem ist, dass ich irgendwann auf dem Main-Thread lande, und dort ohne Invoke eben nicht sehr weit komme, da irgendwann später auch GUI-aufrufe stattfinden würden.

    Ich Frage mich nun, wenn ich nun weg zwei wie gesagt Implementiere, und ein Event Feuere, in welchem Thread läuft dann das ganze ab? Im Main-Thread, der das Event Abboniert hat? Oder in dem Thread(-Pool) der das Event gefeuert hat? Wenn letzteres der Fall ist, wie bekomme ich das Feuern des Events in den Main-Thread, ohne die Invokes einer Form o.ä. zu haben?
    Moin,

    normalerweise kümmert sich der Empfänger der Events um das Invoken. So fällt mir nur ein, dass du eine Form-Instanz als Parameter an den Konstruktor übergibst und dann die Events mittels Invoke feuerst.
    Mit freundlichen Grüßen,
    Thunderbolt
    Wenn es noch keine Form gibt, ist es natürlich etwas schwieriger. Da kannst du z. B. eine Property setzen, in die sich die Form beim Erstellen einträgt. Es muss dann beim Eventfeuern natürlich geprüft werden, ob da eine Form eingetragen ist.

    Ach, mir kommt da gerade noch eine Idee: ​Application.OpenForms
    Mit freundlichen Grüßen,
    Thunderbolt
    Ich habe mal mit dem SynchronizationContext gearbeitet, um Events im Thread der Form zu feuern, aber wenn du kein Objekt hast, das ein anständiges SyncronizationConext-Objekt implementiert hat, gäbe es noch irgendwas mit "Bit-".
    Hier hier und hier noch was. ;)
    Hi
    das Problem mit dem Threading ist hier wohl so zu verstehen, dass es losgelöst von GUI, usw. stattfindet. Schau' dir mal
    - SyncLock
    - Monitor (Monitor.Wait, Monitor.Pulse(All))
    und ggf. zusätzlich
    - Mutex
    - AutoResetEvent, ManualResetEvent
    - Semaphore
    an (liegen alle in System.Threading). Damit lässt sich eine einfache Synchronisation umsetzen.

    Die GUI kann sich ja später dann selbst so an das Konzept anpassen, dass es funktioniert.

    Viele Grüße
    ~blaze~
    Ich nutze eigentlich immer ​ISynchronizeInvoke für das threadsichere Feuern von Events: Man kann eine Form, ein Control oder was auch immer sonst mitgeben und dann aus dessen Thread das Event feuern. Mehr braucht man eigentlich nicht.
    Synclock ist keine Option, wenn deine Events explizit Gui-Thread landen sollen.
    Synclock verhindert nur, dass ein anderer Thread gleichzeitig das Event raist. Dass das verhindert ist, ändert aber nichts daran, dass das Event noch im NebenThread ausgelöst wird.
    Also vergiss Synclock erstmal, und löse das Problem mit OpenForms(0).BeginInvoke, oder SynchronisizeContext.BeginInvoke, oder Dispatcher.BeginInvoke (Wpf) oder wasses da alles für gibt.

    Mit OpenForms isses in eine WinForms-Anwendung am einfachsten, denn dann weißt du auch, wenn gar kein Form (mehr) da ist, und kannst das Event auch unterdrücken.

    gugge auch codeproject.com/KB/vb/AsyncWorker2.aspx
    Nein, das stimmt so nicht. Die Gui selbst ist verantwortlich, ihre Funktionalität zu erfüllen, insofern ist ein asynchroner callback auch nur dort mit der Nachrichtenschleife zu synchronisieren. Zur Synchronisation ASYNCHRONER Vorgänge kann dann die obige Funktionalität benutze werden. Die Gui hat aber auf Verarbeitungsebene nichts zu suchen und wozu etwas serialisiert ausführen, was weiterhin generell asynchron ablaufen kann.

    Viele Grüße
    ~blaze~