Ist es falsch, einen Thread / Background Worker in eine Klasse zu stecken?

15

Ich habe eine Klasse, die aus Excel (C # und .Net 4) liest, und in dieser Klasse habe ich einen Hintergrund-Worker, der die Daten aus Excel lädt, während die Benutzeroberfläche reagieren kann. Meine Frage lautet wie folgt: Ist es schlechtes Design, einen Hintergrundarbeiter in einer Klasse zu haben? Soll ich meine Klasse ohne sie erstellen und einen Hintergrund-Worker verwenden, um diese Klasse zu bearbeiten? Ich kann keine Probleme damit sehen, meine Klasse auf diese Weise zu erstellen, aber andererseits bin ich ein Neuling, also dachte ich, ich würde sicherstellen, bevor ich weitermache.

Ich hoffe, dass diese Frage hier relevant ist, da ich nicht denke, dass es sich um einen Stackoverflow handeln sollte, da mein Code funktioniert. Dies ist nur ein Designproblem.

Jetti
quelle
3
warum denkst du, könnte es falsch sein?
Alb
1
@Alb - es ist schwer zu sagen. Mein Code funktioniert und erfüllt meine Anforderungen. Ich plane jedoch, ihn in einem Projekt zu verwenden, das ich als Open Source-Version bereitstellen werde. Ich möchte sicherstellen, dass mein Code nicht "nur funktioniert" und tatsächlich gut gestaltet ist.
Jetti

Antworten:

21

Soll ich meine Klasse ohne sie erstellen und einen Hintergrund-Worker verwenden, um diese Klasse zu bearbeiten?

Ja du solltest. Und ich werde Ihnen sagen, warum - Sie gegen das Prinzip der einheitlichen Verantwortung verstoßen . Durch die enge Kopplung der Klasse , die die Excel - doc greift mit , wie es greift auf die Excel - doc, beseitigen Sie die Möglichkeit , für die „Controller“ Code (Code, der verwendet diese) ist es eine andere Art und Weise zu tun. Wie anders, könnten Sie fragen? Was ist, wenn der Controller-Code zwei Operationen enthält, die lange dauern, aber sequentiell ausgeführt werden sollen? Wenn Sie dem Controller die Möglichkeit gegeben haben, das Threading zu verarbeiten, kann er beide Aufgaben mit langer Laufzeit in einem Thread gleichzeitig ausführen. Was ist, wenn Sie aus einem Nicht-UI-Kontext auf das Excel-Dokument zugreifen möchten und es nicht als Thread ausgeführt werden muss?

Indem Sie die Verantwortung für die Weiterleitung an den Anrufer übertragen, können Sie den Code flexibler und wiederverwendbarer gestalten.

Nemi
quelle
2
+1 für die Beantwortung der tatsächlich gestellten Frage und die richtige Beantwortung.
Adam Lear
+1 - Danke Nemi. Sie haben meine Frage genau beantwortet, ich weiß das zu schätzen. Ich werde das aus meiner Klasse herausziehen und es in eine neue Klasse stecken, nochmals vielen Dank!
Jetti,
@Nemi - wäre es also akzeptabel, wenn ich eine andere Methode erstellen würde, die synchron geladen würde und dann eine asynchrone Methode hätte? Oder wäre es einfach besser, die eine synchrone Lademethode zu haben und dann von dort zu gehen?
Jetti
1
Ich persönlich hätte keine Synchronisationsmethode und keine asynchrone Methode. Sie übernehmen weiterhin die Verantwortung. Ich habe viele Male mit genau diesem Problem gearbeitet. Was ich getan habe, war ein TaskController, der SwingWorker nachgebildet war, aber spezifischen Code für unsere App hatte. Der TaskController hat beispielsweise eine Fortschrittsanzeige aktualisiert, den Mauszeiger geändert usw. Es scheint, als müsste immer ein TaskController erstellt werden, um Anrufe zu tätigen. Letztendlich ist der Code jedoch robuster und wartungsfreundlicher.
Nemi
Danke Nemi! Ich wünschte, ich könnte dich wieder positiv bewerten, weil du meine Frage definitiv beantwortet und mich in die richtige Richtung gelenkt hast. Danke nochmal!!
Jetti
3

Es ist ein gutes Design, wenn UI-Vorgänge in einem von Hintergrundaufgaben getrennten Thread ausgeführt werden. Andernfalls reagiert die Benutzeroberfläche nicht mehr, wenn die Anwendung ausgelastet ist.

Wenn Sie den Teil, der im Hintergrund-Thread funktioniert, in eine eigene Klasse unterteilen können, wird der Code sauberer.

Alb
quelle
1
Obwohl es richtig ist, wie ich seine Frage gelesen habe, hat er kein Problem damit, diesen Punkt zu verstehen.
Nemi
Es tut mir leid, wenn meine Frage falsch gelesen wurde. Ich weiß, dass das Trennen der Benutzeroberfläche und der Hintergrundaufgaben ein gutes Design ist (falls nicht erforderlich, ist meine Test-Excel-Datei länger als 8.000 Zeilen und lässt das Programm nicht mehr reagieren). Meine Frage ist im Grunde ist es gut, den Thread mit der Excel-Klasse eng zu koppeln.
Jetti
0

Ich würde Ihre Benutzeroberfläche mit separaten Klassen von Ihrer Hintergrundaufgabe trennen. Dies fördert die Trennung von Bedenken. UI-Code und Geschäftslogik sollten nicht gemischt werden.

Ryan Michela
quelle
Um es klar zu sagen, meine Klasse berührt die Benutzeroberfläche nicht. Es gibt zwei Ereignisse, die es ermöglichen, die Benutzeroberfläche bei Bedarf zu aktualisieren, aber meine Klasse selbst berührt die Benutzeroberfläche nicht.
Jetti
0

Was ich an BackgroundWorkers erinnere, ist, dass sie eine Reihe von Convenence-Methoden bereitstellen, beispielsweise die Möglichkeit, Fortschrittsaktualisierungen an die Benutzeroberfläche zu senden. Es gibt jedoch keine Regel, die besagt, dass Sie es nicht aus einer anderen Klasse verwenden können.

Wenn Sie eine Iteration ausführen, bei der keine Elemente in einer bestimmten Reihenfolge verarbeitet werden müssen, sollten Sie stattdessen den ThreadPool verwenden (oder unter .NET 4 die Task Parallel Library verwenden ).

Michael Brown
quelle
Vielen Dank für Ihre Antwort. Ich habe in meiner Klasse zwei Ereignisse erstellt, die den Fortschritt auslösen (im Grunde genommen das BackgroundWorker-Fortschrittsereignis, da der BackgroundWorker privat ist), wodurch der Fortschritt an die Benutzeroberfläche gesendet wird (Fortschrittsanzeige).
Jetti