Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Thread-Synchronisierung, Pause, auf Hardware-Event warten...
7.e.Q
myCSharp.de - Member

Avatar #avatar-3402.jpg


Dabei seit:
Beiträge: 938
Herkunft: Scheeßel

Themenstarter:

Thread-Synchronisierung, Pause, auf Hardware-Event warten...

beantworten | zitieren | melden

Hi Leute,

ich habe hier ein Problem, das mir das Gehirn ein wenig vermust... folgendes:

in einer Anwendung wird ein IronPython-Script ausgeführt, das sequenziell bestimmte Methoden einer C#-Klasse abarbeitet. Diese Methoden laufen im IronPython-Thread synchron, blockieren also die Ausführung des IronPython-Scripts, sodass jede Methode wirklich erst dann aufgerufen wird, wenn die vorherige beendet ist.

Intern laufen diese Methoden hingegen asynchron. Sie führen in einem eigenen Thread ein Kommando auf einer Hardware aus und der Thread wartet dann auf ein von der Hardware ausgelöstes Complete-Ereignis. Dieses Ereignis lässt die Methode dann letztlich auch im IronPython-Script zurückkehren und selbiges die nächste Methode starten. Das funktioniert bis jetzt ganz brauchbar, auch wenn ich da noch auf die echten Thread-Sync Mechanismen verzichte und an deren Stelle quick'n'dirty zyklisch eine volatile bool'sche Variable abfrage. Beziehungsweise derer zwei, weil die Methoden eigentlich immer darauf warten müssen, dass genau zwei Geräte "Complete" zurückmelden.

Darüber hinaus möchte ich nun aber eine Möglichkeit einbauen, die Ausführung der einzelnen Methoden aus einem anderen Thread heraus zu pausieren. Das heißt, es soll nicht mehr nur auf die "Complete"-Ereignisse der Hardware gewartet werden, sondern zusätzlich und nur sofern von außen angefordert noch auf ein "Vorgang-Fortsetzen"-Ereignis.

Wie ist bei so etwas der Königsweg, um das zu erreichen? Welche Mechanismen zur Threadsynchronisierung nutzt man dabei am besten?

Vielen Dank!

Cheers,
Hendrik

//edit: by the way: ich nutze async/await und Task
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von 7.e.Q am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo 7.e.Q,

AutoResetEvent, siehe Consolenanwendung mit Timer optimieren [Semaphore/Ampel].

Und deine Busy-Waiting-Schleife kannst du auch gleich dadurch ersetzen.

herbivore
private Nachricht | Beiträge des Benutzers
weismat
myCSharp.de - Member



Dabei seit:
Beiträge: 878
Herkunft: Frankfurt am Main

beantworten | zitieren | melden

Du hast ein typisches Producer/Consumer Pattern und da wuerde ich auf eine BlockingCollection zurueckgreifen.
Der Producer koennte zum Beispiel an den Consumer einen Parameter mit der Ergebnis-BlockingCollection mit. Der Consumer schreibt dann sein Ergebnis in die Collection (Add-Methode) und der Producer wertet das Ergebnis aus (Take auf die Collection) und prueft nach jedem empfangenen Ergebnis, dass keine weiteren Ergebnisse ausstehen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von weismat am .
private Nachricht | Beiträge des Benutzers
7.e.Q
myCSharp.de - Member

Avatar #avatar-3402.jpg


Dabei seit:
Beiträge: 938
Herkunft: Scheeßel

Themenstarter:

beantworten | zitieren | melden

Okay, das mit den WaitHandles funktioniert. Ist allerdings gewaltige Hirnvermusung. Parallel in Threads zu denken, macht keinen Spaß. Gibt es da Methoden, die das Mitdenken bei Multithreading-Anwendungen vereinfachen, den Kopfcompiler verbessern?

Alter Falter...
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16110

beantworten | zitieren | melden

Wenn Deine Schichten an für sich sauber sind, dann spielt der Hauptthread in Deiner Business-Schicht ja keine Rolle mehr.
Und wenn das alles sauber umgesetzt ist dann sollte das auch keine Hirnvermusung sein.

Ich mach das oft so, dass Instanzen in einem eigenen Thread laufen und darin parallelisiert wird. Klassisches Beispiel ist hier ein Kern von mir, der Ablagen überwacht und synchron hält.
Die Synchronisierung von Dateien läuft parallel in einem Thread. Sollte die GUI geöffnet sein, dann werden zusätzlich Events an den UI-Thread gepusht.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
7.e.Q
myCSharp.de - Member

Avatar #avatar-3402.jpg


Dabei seit:
Beiträge: 938
Herkunft: Scheeßel

Themenstarter:

beantworten | zitieren | melden

Zitat von Abt
Und wenn das alles sauber umgesetzt ist dann sollte das auch keine Hirnvermusung sein.

Und genau das ist das Problem... Die Anwendung ist über Jahre gewachsen, nein, lass es mich "gewuchert" nennen. Da ist leider nichts mehr sauber drin umgesetzt. Aber um von vorn anzufangen und all die Erfahrungen, die ich im Laufe der Zeit gemacht habe, sauber in einer neuen Software zu verpacken, fehlt leider auch die Zeit. ****** Deadline.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo 7.e.Q,

was für Fälle man bei nebenläufiger Programmierung beachten muss, zeigt das Beispiel mit zwei konkurrierenden Consumern in SyncQueue <T> - Eine praktische Job-Queue (und die von dort verlinkten Beispiele im Programmierspiel). Davor gibt es keinen Schutz. Anderseits ist es einfach eine Sache von Erfahrung und Übung, solche Fälle zu berücksichtigen und zu durchdenken. Ich versetze mich immer in die Rolle des bösen Onkels, der die fiesest mögliche Situation konstruiert, die ungünstigsten Zeitpunkte für Thread-Wechsel wählt, immer die unpassendsten und grenzwertigsten Daten verwendet, die den Programmablauf möglichst stark durcheinander bringen. Ich versuche nicht zu zeigen, dass der Code in normalen Situationen korrekt ist, sondern ich versuche auf Biegen und Brechen in der abwegigsten Situation doch noch einen Fehler zu finden. Wie gesagt, eine Übungssache. Natürlich muss man dazu die Funktionsweise und die Besonderheiten der Synchronisierungsmechanismen genau kennen. Also Wissen und Erfahrung.

Natürlich kann man versuchen, besonders haarige Stellen zu kapseln, wie es die SyncQueue macht, damit der Benutzer der Klasse weniger Probleme hat. Aber das geht nur bis zu einem gewissen Grad. Es gibt keinen Königsweg. Wenn man versucht, die Komplexität des Synchronisation vor dem Benutzer des Konstrukts zu verstecken, tut man ihm keinen Gefallen, wie das async/await-Beispiel in Task, die mit async/await arbeitet, kehrt vorzeitig zurück zeigt.

herbivore
private Nachricht | Beiträge des Benutzers