lilith2k3 Geschrieben 13. November 2010 Geschrieben 13. November 2010 Hallo liebe Programmierkundigen, kennt jemand von Euch Tutorials, Bücher etc. zum Thema Multithreading in C#? Ich möchte gern eine etwas komplexere Anwendung schreiben, habe aber noch keine Ahnung, wie man sowas in C# multithreaded umsetzen kann. Allgemeine Sachen habe ich quasi zu Hauf im Netz gefunden (Background Worker, Threads mit Lamda-Ausdrücken, Threadpools etc.). Allerdings kratzt das für meine Bedürfnisse zu sehr an der Oberfläche. Mir schwebt folgendes vor: Meine Anwendung hat 2+ parallele Threads laufen, über welche ich einen Webservice ansteuern möchte. Dort werden Daten in einer Datenbank abgelegt. Mit den jeweiligen (temporären) Antworten arbeiten derweil die anderen Threads weiter. Beispiel: Ich habe eine Liste von Kontaktpersonen. Jede Kontaktperson ist einer Firma zugeordnet. Ich habe dann quasi zwei Listen (1) Alle Firmen und (2) Alle Kontakte. Thread 1 startet damit, alle Firmen der Reihe nach in die Datenbank zu pusten. Jedesmal, wenn eine Firma neuangelegt worden ist, erhalte ich eine Guid zum entsprechenden Datensatz zurück. Ist die Firma allerdings schon vorhanden, ermittele ich die Guid. Die Guid lege ich in einem Container in welchem beide Threads Zugriff haben sollen ab. Thread 2 "pollt" quasi den Container und sobald da eine Guid drin liegt, werden die entsprechenden Kontakte der Firma, deren Guid im Container abgelegt worden ist, in die Datenbank geblasen. Alternativ hab ich auch schon an Events gedacht, so dass quasi der Container dem zweiten Thread "Bescheid" sagen kann; "Hey, Junge, hier gibt's was!". Wie gesagt, es ist ein recht komplexes Thema. Ich bin dankbar für jede Hilfestellung, bzw. jeden (Literatur)Tip. Zitieren
flashpixx Geschrieben 13. November 2010 Geschrieben 13. November 2010 Ich würde das erst einmal unabhängig von C# designen. Ich würde eine zentrale Datenstruktur bauen, in die ein entsprechendes Locking implementiert ist. Ein Thread legt dort entsprechend einen Datensatz ab, wenn er die Antwort erhalten hat und die anderen Threads aus dem Pool entnehmen diese Daten. Wobei ich das auch als Warteschlange implementieren würde, damit Du eine definierte Abfolge haben. Eine Sache ist dabei zu beachten: Wie verhalten sich die Threads, wenn die Warteschlange leer ist, denn die Threads zu beenden ist dann sicherlich nicht in Ordnung, denn es können können einfach (noch) keine Daten in der Schlange sein. Ein Eventhandling halte ich hier für nicht sinnvoll, denn Du hast ja keine deterministische Struktur, d.h. das auf ein Event muss eine bestimmte Aktion erfolgen. In Deinem Fall ist es ja egal, wann und wer den Datensatz verarbeitet, er muss nur verarbeitet werden und letzteres stellst Du ja sicher, so lange die Warteschlange nicht leer ist, muss gearbeitet werden. Technisch würde ich mit einem Threadpool arbeiten und eben eine Strukturvorsehen, die die Daten aus dem Webservice holt und vorbereitet. Wenn ein Thread eben einen Call des Webservice verarbeitet hat, schreibst Du in eine Warteschlange eben eine ID und gibst den Thread in den Pool. Threads die im Pools sind holen sich dann die ID und arbeiten dann die konkrete ID ab. Evtl machst Du zwei Pools, einen für den Webservice Call und einen für die nachfolgende Verarbeitung. Ich denke aber, das Vorgehen musst Du dann konkret entscheiden. Ein Ziel wäre eben die Aufgaben so weit unabhängig zu designen, weil dann das Threading eben sehr effizient ist, damit solltest Du eben nur schauen wo Du synchronisiert arbeiten musst Zitieren
Guybrush Threepwood Geschrieben 13. November 2010 Geschrieben 13. November 2010 Ich bin in .Net leider nicht so auf dem laufenden aber vor dem Release von Visual Studio 2010 hieß es doch mal das das neue .Net Framework Klassen mitbringen soll die Operationen automatisch auf mehrere Kerne aufteilen sollen. Also zum Beispiel eine neue foreach Schleife die Ihre durchläufe automatisch multithreaded und auch irgendwie wieder automatisch synchronisiert. Was ist denn daraus geworden? Evtl hilft dir das ja weiter... Ansonsten ist der Backgroundworker schon eine einfache Methode etwas parallel auszuführen. Zitieren
NerdonRails Geschrieben 13. November 2010 Geschrieben 13. November 2010 Nennt sich TPL (Task Parallel Library). Parallel Performance: Optimize Managed Code For Multi-Core Machines Zitieren
flashpixx Geschrieben 13. November 2010 Geschrieben 13. November 2010 Das Problem aber bei der TPL ist, dass ein Optimierung hier relativ wenig bringt, sprich der Parallelisierungsgrad ist nicht hoch (Berechnen kann man das im Limes über das Gesetz vom Amdahl bzw Gustafsons). Wenn man Algorithmen parallelisiert (egal ob Multithread oder Multicore), dann muss man das Problem analysieren und eben sich die Daten- und Berechnungsflüsse anschauen. Auf dieser Ebene bringt eine Parallelisierung den meisten Speed-Up. Eine reine Optimierung auf TPL, also Schleifenoptimierung, bringt weniger Speed-Up. Der Ansatz ist letztendlich die Problemstellung und deren Abhängigkeiten Zitieren
NerdonRails Geschrieben 13. November 2010 Geschrieben 13. November 2010 Die TPL besteht nicht nur aus den parallelisierten Schleifen. Einen weiteren Einblick gibt : Parallel Programming: Task Schedulers and Synchronization Context - C# Frequently Asked Questions - Site Home - MSDN Blogs Ich sage nicht, das die TPL das allheilmittel ist, aber es nimmt einem schon einen großen Teil der Sorgen ab, die man sonst in Sachen Threading befürchten muss. Weiterhin bestimmt laut MSDN soweit ich es gelesen habe die optimal Anzahl an Threads etc. selbst, was einem diese weitere Sorge auch abnimmt. Zitieren
flashpixx Geschrieben 13. November 2010 Geschrieben 13. November 2010 Ich sage nicht, das die TPL das allheilmittel ist, aber es nimmt einem schon einen großen Teil der Sorgen ab, die man sonst in Sachen Threading befürchten muss. Das wollte ich ja eigentlich ausdrücken. Parallelisierung kann man eben auf verschiedenen Ebenen durchführen, wobei man eben immer im Kopf haben muss, dass eben manche Konzepte einen höheren Parallelisierungsgrad bieten. Ich denke, wenn man sich überlegt was man überhaupt parallelisieren will und dann die passende Technik wählt, erhält man eine gute Lösung. Einfach ein Toolkit zu verwenden zu hoffen, dass dieses das schon alles irgendwie erledigt, führt nicht zum Ziel Zitieren
NerdonRails Geschrieben 13. November 2010 Geschrieben 13. November 2010 Ich denke, wenn man sich überlegt was man überhaupt parallelisieren will und dann die passende Technik wählt, erhält man eine gute Lösung. Einfach ein Toolkit zu verwenden zu hoffen, dass dieses das schon alles irgendwie erledigt, führt nicht zum Ziel Dem stimme ich zu. Zitieren
lilith2k3 Geschrieben 14. November 2010 Autor Geschrieben 14. November 2010 Vielen Dank ersteinmal soweit :] .NET 4.0 scheidet voraussichtlich aus. Ich habe bei der Verwendung von .NET 4.0 und einigen (microsofteigenen) Ressourcen, welche ich einbinden muss Probleme gehabt, die bei Target .NET 3.5 nicht aufgetreten sind (gleicher Code wohlgemerkt). Insofern fällt die TPL und so Schnickschnack wie PLINQ ersteinmal flach :/ Alldieweil hab ich was interessantes im Netz gefunden ... Threading in C# - Part 4 - Advanced Threading muss ich mir mal morgen oder so anschauen :] Zitieren
lilith2k3 Geschrieben 18. November 2010 Autor Geschrieben 18. November 2010 Den/die Artikel kann ich nur weiterempfehlen :] Das passt genau zu meinem Problem. Ich habe es nun so gelöst, dass ich ein Containerobjekt geschaffen habe, welches ich mit einem public readonly object ContainerLock = new object(); versehen habe. Den Consumer Prozess kann ich dann bequem mit Monitor.Wait(con.ContainerLock) in den Wartezustand versetzten. Und wenn der Producer wieder was in die Queue gefüllt hat, kann ich mit Monitor.Pulse(con.ContainerLock); Bescheid geben. Exzellent! :] Zitieren
Argbeil Geschrieben 24. November 2010 Geschrieben 24. November 2010 Solche Lösungen scheitern häufig an der Anwendungsarchitektur, in der Regel macht man sich die Parallelität durch locking wieder kaputt. Zudem hat man in deinem Anwendungsfall vermutlich weitere Probleme, die Datenmengen sind einfach zu klein und führen zu Locks auf Hardware-Ebene. Der IIS als Webserver kann die Requests ja auch schon von Haus aus auf verschiedene Cores verteilen. Ich würde dir empfehlen eine Architektur wie Event Based Components zu verwenden. Die Komponenten sind komplett statuslos und brauchen dadurch kein locking. Wenn die Anwendung erstmal ohne Threading fertig ist kann man jede einzelnen Komponente paralelisieren. Ich wage aber die Prognose das die parallele Lösung trotzdem langsamer laufen wird als die synchrone. Zitieren
lilith2k3 Geschrieben 24. November 2010 Autor Geschrieben 24. November 2010 in der Regel macht man sich die Parallelität durch locking wieder kaputt Werde ich (wenn ich demnächst mal wieder dazu komme) in der Praxis austesten müssen. Wenn die Anwendung erstmal ohne Threading fertig ist kann man jede einzelnen Komponente paralelisieren. Ich wage aber die Prognose das die parallele Lösung trotzdem langsamer laufen wird als die synchrone. Die Anwendung ist soweit fertig. Daher kam ich auch auf den Gedanken, das, was vorher seriell ablief, zu parallelisieren :] Vorallem natürlich erstmal mit dem Hintergedanken, was Neues auszuprobieren und etwas zu lernen. Ich würde dir empfehlen eine Architektur wie Event Based Components zu verwenden. Die Komponenten sind komplett statuslos und brauchen dadurch kein locking. Kennst Du gute Quellen (im Netz)? Zitieren
NerdonRails Geschrieben 24. November 2010 Geschrieben 24. November 2010 Auf One Man Think Tank Gedanken: Event-based Components gibts einige Artikel zu dem Thema EBCs Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.