Laden...

Dateizugriffe in separaten Tasks trotzdem sequentiell abarbeiten

Erstellt von Taladan vor 10 Jahren Letzter Beitrag vor 10 Jahren 2.650 Views
Taladan Themenstarter:in
582 Beiträge seit 2008
vor 10 Jahren
Dateizugriffe in separaten Tasks trotzdem sequentiell abarbeiten

Hallo,

ich habe ein Problem mit meinen Dateizugriffen. Ich lasse die Dateizugriffe in separaten Tasks laufen und versuche sie trotzdem "der reihe nach" abzuarbeiten.

Leider funktioniert das nicht, wie gewünscht, die Task kommen sich trotzdem noch gegenseitig ins Gehege. Evtl funktioniert das lock nicht korrekt. aber ich frage mich, ob es nicht evtl sogar verbreitete Lösungen gibt. Immerhin sollte ein TaskStack nicht so selten verwendet werden, oder?

Gruß dat Tala

16.842 Beiträge seit 2008
vor 10 Jahren

Du wirst das parallel nicht sauber hinbekommen, da eine Datei minimal verzögert ge/-entlockt wird.
Ergo als Shared öffnen oder sequentiell arbeiten (was auch die empfohlene Variante ist).

Was hast Du denn vor, dass es parallel sein muss?
Performanter bist Du dadurch nicht - im Gegenteil sogar.

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 10 Jahren

Windows Rt verlangt es, dass sie Dateizugriffe Asyncron sind.

das speichersstem, welches ich erdacht, ist recht komplex. Es gibt zwei vereichnisse je objekt. Eines mit Originaldaten und eines mit änderungen, die nur die änderungen enthalten und die id, alles was original ist, taucht in der änderungsdatei nicht auf. Das macht das system sehr flexibel.

Mein problem ist es nun die dateien zusammen zu laden, dabei zu verbinden. Derweil kann der anwender aber schon änderungen vor nehmen. Jede änderung wird direkt aus die platte gesichert.

Warum sich das ins gehege kommt. Ist mir noch nicht so ganz klar, aber ich teste erst mit 10 datensätzen und später kommen hunderte dazu.

Gruß dat Tala

16.842 Beiträge seit 2008
vor 10 Jahren

Dann solltest Du auch sagen, dass Du mit WinRT arbeitest - wir können nicht hellsehen.

Aber warum das nicht funktioniert ist klar: Du versuchst auf ein Handle zuzugreifen, was noch gesperrt ist.
Für sowas verwendet man im Prinzip Singletons, die eine Synchronität garantieren.
Inwiefern das mit WinRT im Einklang steht; weiß ich nicht.

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 10 Jahren

Ich setzte schon singletons ein, aber die dateiaufruffunktion an sich ist bereits ein thread

Gruß dat Tala

742 Beiträge seit 2005
vor 10 Jahren

Verwende tasks mit einem scheduler, der nur ein thread verwendet.

How to: Create a Task Scheduler That Limits Concurrency

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Taladan,

Windows Rt verlangt es, dass sie Dateizugriffe Asyncron sind.

stimmt und das finde ich auch nervig. Aber anderseits gibt es ja async/await, so dass man, wenn man die Methode mit den Aufrufen als async kennzeichnet, mit await auf die Beendigung des jeweiligen asynchronen Aufrufes "warten" kann. Wenn du also die Aufrufe, die sequentiell ausgeführt werden sollen, (sequentiell) in eine mit async gekennzeichnete Methode schreibst und vor jeden Aufruf await schreibst, sind zwar verschiedene Tasks an der Ausführung beteiligt, aber der Gesamtablauf ist trotzdem sequentiell.

Immerhin sollte ein TaskStack nicht so selten verwendet werden, oder?

Du meinst wohl Task_Queue_, siehe z.B. SyncQueue <T> - Eine praktische Job-Queue.

herbivore

Taladan Themenstarter:in
582 Beiträge seit 2008
vor 10 Jahren

Das ist so aber nicht ganz richtig. Await wartet nicht, sondern lässt beide Prozeduren weiter laufen. Nur am ersten Vorkommnis, wo auf die Variable, die mittels Await befüllt wird, zu gegriffen wird, wird (ggf) gewartet.

Ich persönlich finde das Konzept von Async/Await sehr verwirrend und es wird viel zu häufig falsch verstanden.

Gruß dat Tala

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo Taladan,

Das ist so aber nicht ganz richtig.

die Kernaussage, dass mehrere asynchrone Aufrufe sequelltiell (also einer nach dem anderen) ausgeführt werden, wenn sie alle mit await gekennzeichnet sind, ist schon richtig. Zumindest halte sich sie bis zum Beweis des Gegenteils für richtig.

Await wartet nicht, sondern lässt beide Prozeduren weiter laufen.

Deshalb hatte ich "warten" auch in Anführungszeichen geschrieben. Richtig ist, dass auch der Thread weiterläuft, der das await "ausführt". Aber das bedeutet eben nicht, dass er auch schon den folgenden Aufruf ausführt. Der wird erst ausgeführt, wenn die Kontrolle durch das await zurück an die mit async gekennzeichnete und durch Compiler-Magic unterbrochene Methode übergeben wird.

Nur am ersten Vorkommnis, wo auf die Variable, die mittels Await befüllt wird, zu gegriffen wird, wird (ggf) gewartet.

Das kann ich so nicht unterschreiben. Möglicherweise verstehe ich auch nur nicht, was du meinst.

Ich persönlich finde das Konzept von Async/Await sehr verwirrend und es wird viel zu häufig falsch verstanden.

Das sehe ich ganz genauso. Da man durch die vielen asynchronen Methoden von WinRT aber dazu gezwungen wird, mit der erzwungenen Asynchronität umzugehen, muss man irgendeinen Tod sterben. Und da ist dann async und await - richtig eingesetzt - durchaus eine Option.

Eine andere Option habe ich mit der SyncQueue bzw. der BlockingCollection durchaus auch genannt.

herbivore

742 Beiträge seit 2005
vor 10 Jahren

Ich wiederhole es nochmal:

Verwende den oben geposteten Task-Scheduler. Dann kannst du sicherstellen, dass alle I/O Sachen in einem einzigen Hintergrund-Thread laufen und du kannst ja trotzdem noch async-await verwenden um bequem deine UI zu aktualisieren.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo malignate,

also zumindest ich hatte deinen Beitrag gelesen. Allerdings ist das aus meiner Sicht nur eine Lösung unter mehreren.

Außerdem ist mir noch nicht klar, wie du die Tasks bzw. ThreadPool-Threads, die von den asynchronen Methoden von WinRT benutzt werden, dazu überreden willst, den LimitedConcurrencyLevelTaskScheduler zu benutzen. Im Beispielcode werden die Tasks ja über eine Factory erzeugt, der man den LimitedConcurrencyLevelTaskScheduler explizit übergibt. Wie macht man das bei Tasks, die man nicht selber erzeugt?

herbivore