Laden...

async - Wie komplexe Objekte am besten während lang laufendem Task zurückgeben/synronisieren?

Erstellt von Scavanger vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.835 Views
Scavanger Themenstarter:in
309 Beiträge seit 2008
vor 8 Jahren
async - Wie komplexe Objekte am besten während lang laufendem Task zurückgeben/synronisieren?

Servus,

wie kann ich am besten während eines laufenden Tasks Daten an den Aufrufer zurückgeben bzw. synchronisieren ohne das es zu Race conditions oder Dead locks kommt?

Mein Ansatz bisher:


class AsyncPolling
{
    public object Obj { get; private set; }

    public async Task PollAsync(IProgress<bool> progress, CancellationToken ct)
    {
        await Task.Run(() =>
        {
           while (true)
           {                   
               // Process some data...
               if (data_has_changed)
               {
                   Obj = ...
                   progress.Report(true);
               }
               ct.ThrowIfCancellationRequested();
          }
       }, ct);
    }
}

In der schleife frage ich ständig ein Gerät ab (per Polling, geht leider nicht anders), das die Zustände in _o speichert. _o ist relativ komplex. Die Daten sollen dann weiterverarbeitet bzw. angezeigt werden.
Ich würde ungern Obj über IProgess<T> schleusen, am liebsten wäre mir wenn ich darüber dem Aufrufer nur mitteile das neue Daten vorliegen und der die sich die aus dem Property holt.
Muss ich das Property noch locken oder ist das bei async .. await nicht nötig?

Oder ist der Ansatz zu naiv und ich bin komplett auf dem Holzweg?

using System;class H{static string z(char[]c){string r="";for(int x=0;x<(677%666);x++)r+=c[
x];return r;}static void Main(){int[]c={798,218,229,592,232,274,813,585,229,842,275};char[]
b=new char[11];for(int p=0;p<((59%12));p++)b[p]=(char)(c[p]%121);Console.WriteLine(z(b));}}

1.029 Beiträge seit 2010
vor 8 Jahren

Hi,

nun - die eigentliche Frage sollte in meinen Augen eher lauten:

Wie willst du denn bitte deinem Aufrufer sagen, dass sich was am Objekt geändert hat bzw. ein Schleifen-Durchlauf abgeschlossen ist?

In der Regel macht man sowas mit einem eigenen Event, welches vom Aufrufer abonniert wird.

Und wenn man dann ohnehin ein eigenes Event hat - ist es zudem recht intelligent diesem auch ein Property in Form des Objekts, welches der Aufrufer gerne hätte mitzugeben.

Was multithreading angeht:
a) Ich würde i.d.R. nicht versuchen ein einziges Objekt immer wieder zu benutzen - du weisst doch gar nicht, ob das alte und die alten Werte gerade noch in Arbeit sind und was damit gerade geschieht - ich fände es z.B. echt kacke, wenn gerade einzelne Eigenschaften des objects irgendwo geloggt werden - und dann dein Task mitten im Loggen anfängt Sachen zu ändern, womit im Endeffekt Mist geloggt wird
b) Primäres Augenmerk wird somit dabei liegen, dass die UI nicht abschmiert // Control.Invoke bzw. WPF-Gegenstück dazu
c) Folgendes würde ich mir zu Multithreading anschauen: http://www.albahari.com/threading/

LG

16.834 Beiträge seit 2008
vor 8 Jahren

Async ist nicht dazu da, dass möglichst viel Parallel läuft, sondern, dass gewisse Dinge (wie eine UI) nicht blockieren.
Ansonsten ist Taipi nichts hinzuzufügen: verwende Events.

F
10.010 Beiträge seit 2004
vor 8 Jahren

Oder eine SyncQueue wie die von Herbivore oder diese MemoryQueue

Scavanger Themenstarter:in
309 Beiträge seit 2008
vor 8 Jahren

Servus,

danke für euren Input.

In der Regel macht man sowas mit einem eigenen Event, welches vom Aufrufer abonniert wird.

Und wenn man dann ohnehin ein eigenes Event hat - ist es zudem recht intelligent diesem auch ein Property in Form des Objekts, welches der Aufrufer gerne hätte mitzugeben.

An events hatte ich zu aller erst gedacht, und wollte es ganz modern mit async/await lösen und hab aber überhaupt nichts zu events in Verbindung zu async/await gefunden.

a) Ich würde i.d.R. nicht versuchen ein einziges Objekt immer wieder zu benutzen - du weisst doch gar nicht, ob das alte und die alten Werte gerade noch in Arbeit sind und was damit gerade geschieht - ich fände es z.B. echt kacke, wenn gerade einzelne Eigenschaften des objects irgendwo geloggt werden - und dann dein Task mitten im Loggen anfängt Sachen zu ändern, womit im Endeffekt Mist geloggt wird

Ja guter Punkt, werd ich so umsetzen.

b) Primäres Augenmerk wird somit dabei liegen, dass die UI nicht abschmiert // Control.Invoke bzw. WPF-Gegenstück dazu
c) Folgendes würde ich mir zu Multithreading anschauen:
>

Ich dachte mit Einführung von Tasks sollte man Threads i.d.R. nicht mehr benutzen. 🤔

Mit eurem Input hab ich folgenden Artikel gefunden (Das Stichwort war "Tasks + event" :
Writing thread-safe event handlers with the Task Parallel Library in .NET 4.0

Besonders gefällt mir das das ganze ohne Control.Invoke und Co. auskommt.
In Verbindung TaskCreationOptions.LongRunning, sollte das perfekt für meinen Anwendungszweck sein.

using System;class H{static string z(char[]c){string r="";for(int x=0;x<(677%666);x++)r+=c[
x];return r;}static void Main(){int[]c={798,218,229,592,232,274,813,585,229,842,275};char[]
b=new char[11];for(int p=0;p<((59%12));p++)b[p]=(char)(c[p]%121);Console.WriteLine(z(b));}}

16.834 Beiträge seit 2008
vor 8 Jahren

Async/await ist aber kein Konkurrenzpattern zu Events. Damit werden - im Prinzip - zwei verschiedene Bedarfe abgedeckt.
Du willst hier kontinuierlich Informationen pushen - dafür ist async/await nicht gedacht.

Man darf Threads weiterhin benutzen - dagegen sagt auch niemand was. Es gibt auch Situationen, da musst Du es sogar.
Aber wenn Du kannst, dann solltest Du Tasks benutzen, da sich diese einfacher sowohl für den Entwickler als auch für das System handlen lassen.