(gelöst)[C#] Warum funktioniert das?

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

(gelöst)[C#] Warum funktioniert das?

Beitrag von Krishty »

Ich muss gerade über folgenden Quelltext schauen, der Arbeit in einen separaten Thread auslagern soll:
  • var threadFunc = (SendOrPostCallback)delegate { ...... };

    var job = Dispatcher.BeginInvoke(DispatcherPriority.Background, threadFunc, null);

    job.Completed += ui_onCompletion;
Als Native-Entwickler sah das für mich sofort nach Race Condition aus:
  1. BeginInvoke() startet den Worker
  2. der Worker ist fertig, bevor der Haupt-Thread job.Completed += ui_onCompletion; aufruft
  3. ui_onCompletion() wird niemals aufgerufen und das Programm hängt
Ich wollte diese Race Condition provozieren, und habe es nicht geschafft: threadFunc() wird erst *nach* job.Completed += ui_onCompletion; aufgerufen; egal, was ich mache.

Nun wollte ich prüfen, ob das eine API-Garantie ist. Leider ist die Dokumentation von System.Windows.Threading.Dispatcher.BeginInvoke() und System.Windows.Threading.DispatcherOperation.Completed so gut wie wertlos.

Das Verhalten, das ich beobachte, lässt sich im Augenblick nur erklären durch
  1. Der Worker startet erst, nachdem job aufgeräumt wurde, was durch den Garbage Collector aber nicht deterministisch ist
  2. Der Worker wird in irgendeine Warteschlange eingereiht, die erst abgearbeitet wird, wenn der Haupt-Thread das nächste Mal seine Nachrichten verarbeitet, was aber irgendwie dem Zweck eines Thread Pools widerspricht
Kann mir jemand erklären, warum das funktioniert, und ob dieses Verhalten garantiert (der Code also in Ordnung) ist?
Zuletzt geändert von Krishty am 03.07.2016, 20:25, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: [C#] Warum funktioniert das?

Beitrag von xq »

Dispatcher ist kein Thread Pool sondern eine Möglichkeit, Funktionen im Haupt-Thread aufzurufen. BeginInvoke reiht die Nachricht ein, Invoke wartet auch noch auf die Completion.

Ansonsten kann der Job auch beim Hinzufügen des events darauf reagieren, wenn der Job schon completed ist und das Event dann sofort aufrufen.

Für "richtiges" Thread Pooling guck mal die Klassen Task, Thread und ThreadPool. Falls du in dem Fall den wirklich nen parallelen Thread verwenden willst, empfehle ich dir Task<T> mit await/yield
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C#] Warum funktioniert das?

Beitrag von Krishty »

Also ungefähr meine 2. Vermutung? Und als mein UI-Mann dachte, dass er die Arbeit in einen 2. Thread geschoben hätte, hat er sie in Wirklichkeit in die Idle-Zeit des Haupt-Threads geschoben?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
xq
Establishment
Beiträge: 1581
Registriert: 07.10.2012, 14:56
Alter Benutzername: MasterQ32
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

Re: [C#] Warum funktioniert das?

Beitrag von xq »

Richtig, genau das. Im Normalfall spawnt man einen Task<T> in der UI und gibt das ergebnis entweder mit await/async oder mit dem Dispatcher an den Main Thread zurück
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…

Programmiert viel in ⚡️Zig⚡️ und nervt Leute damit.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [C#] Warum funktioniert das?

Beitrag von Krishty »

Danke vielmals! :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten