dhh Geschrieben 21. Januar 2010 Teilen Geschrieben 21. Januar 2010 Tag zusammen, ich habe eine C#-Form-Anwendung geschrieben die unregelmäßig den Datenbestand in einer betriebsintern eingesetzten Software archivieren soll (in Visual Studio 2008, läuft auf nem Windows Server 2003 in ner Testumgebung). Nach dem Start der Anwendung startet der Admin manuell den Vorgang (ist so vorgegeben) und die Anwendung arbeitet ca. 5 Minuten. Während der ganzen Zeit reagiert das Fenster nicht, im TaskManager steht sie als "reagiert nicht". An Code-Optimierung habe ich schon einiges getan - deshalb jetzt die allgemeine Frage: wie kann ich dafür sorgen dass die Anwendung Fortschrittsbalken, Protokoll-Ausgaben etc. anzeigt während sie weiter arbeitet? Ist es möglich, eine Methode mit niedriger Priorität auszuführen oder so? Wie löst man das professionell? Habe schon nach X Operationen einen Sleep-Timer von 100ms eingebaut, der sorgt auch (recht unzuverlässig) für Anzeige der benötigten Daten aber das kann m.E. doch nicht so gedacht sein. Wie würde ein Profi das lösen - Idee? Danke & Gruß, Daniel Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Bubble Geschrieben 21. Januar 2010 Teilen Geschrieben 21. Januar 2010 Wie würde ein Profi das lösen - Idee? Die Window Messages müssen verarbeitet werden. Wenn der GUI Thread lange beschäftigt ist, muss dies manuell veranlasst werden. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dhh Geschrieben 22. Januar 2010 Autor Teilen Geschrieben 22. Januar 2010 Hallo Bubble, das habe ich jetzt soweit gemacht, mit "Application.doEvents" - funktioniert auch. Nach 25 Schleifen-Durchläufen wird jetzt das Fenster aktualisiert. Gibt es dennoch eine Möglichkeit, eine niedrigere Prozesspriorität festzulegen? Die Anwendung läuft auf nem Server - d.h. es ist vermutlich nicht immer gewünscht dass 50% Prozessorauslastung dadurch verursacht werden. Soweit Danke, Daniel Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Hahne Geschrieben 22. Januar 2010 Teilen Geschrieben 22. Januar 2010 Da deine GUI einfriert würde ich auf das Control BackgroundWorker zurückgreifen. C# BackgroundWorker Tutorial Mit diesem Control kannst du dann z.B. auch den Status in einer Progressbar anzeigen lassen. Hahne.NET : Progressbar im Backgroundworker ansprechen Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
JasonDelife Geschrieben 22. Januar 2010 Teilen Geschrieben 22. Januar 2010 Noch zur Ergänzung: Nimm auf jeden Fall Hahnes Vorschlag! DoEvents() ist mist! Und es hat manchmal unangenehme Nebenwirkungen. Mehr dazu kannst du hier lesen: myCSharp.de - DIE C# und .NET Community | FAQ | [FAQ] Warum blockiert mein GUI? Grüße, JasonDelife. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Bubble Geschrieben 22. Januar 2010 Teilen Geschrieben 22. Januar 2010 Dir Priorität des Prozesses, bzw. des ausführenden Threads muss herabgesezt werden, wenn das Programm andere (wichtigere) Programme möglichst wenig beinflussen soll. Wenn der PC aber im Moment ohnehin nichts macht, ist aber auch eine hohe CPU Auslastung unproblematisch. Die Anwendung in zwei Threads aufzuteilen ist zwar möglich, hat aber andere Schwierigkeiten, da GUI Elemente immer vom GUI Thread aus verändert werden müssen. Wenn die GUI nicht für normale Interaktionen, sondern eher als Statusanzeige, gebraucht wird, würde ich der Einfachheit halber darauf verzichten. DoEvents() ist mist! Begründung (für diesen Anwndungsfall)? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
JasonDelife Geschrieben 22. Januar 2010 Teilen Geschrieben 22. Januar 2010 DoEvents() ist generell schlecht. Nachzulesen im geposteten Link. Dort wird auch ein Artikel verlinkt, der ein paar Probleme aufzeigt: jfo's coding : Keeping your UI Responsive and the Dangers of Application.DoEvents In dem Artikel wird auch die einzige Situation erläutert, wo DoEvents() ok ist: Wenn keine Message Pump läuft, was aber so gut wie nie der Fall ist. Aber sonst NIE. DoEvents() ist nicht dazu gedacht Multithreading abzuschaffen. Der BackgroundWorker bietet gute Möglichkeiten und mit Thread hat man komplette Kontrolle über das Geschehen. DoEvents() kann diese nicht ersetzen und ist auch nicht dazu gedacht (auch wenn man bei manchen MSDN-Artikeln wegen des übermäßigen DoEvents()-Gebrauch den Eindruck bekommt). Ich kann keinem DoEvents() verbieten, aber es soll keiner sagen können, dass er nicht gewarnt wurde . Grüße, JasonDelife. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Bubble Geschrieben 23. Januar 2010 Teilen Geschrieben 23. Januar 2010 Die Funktion erfüllt ihren Zweck. Das eventuelle Seiteneffekte (z.B. durch Benutzer-Interaktion mit dem Form) zu berücksichten und abzufangen sind, versteht sich von selbst. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
JasonDelife Geschrieben 23. Januar 2010 Teilen Geschrieben 23. Januar 2010 Und dann bastelst du ewig daran, die Seiteneffekte abzufangen, obwohl es mit dem BackgroundWorker im Endeffekt schneller und sauberer gewesen wäre. Grüße, JasonDelife. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gateway_man Geschrieben 23. Januar 2010 Teilen Geschrieben 23. Januar 2010 Wenn dir ein wenig mehr schreibaufwand nichts ausmacht kannst du es natürlich auch direkt in einem oder mehreren eigenständigen Threads auslagern. Das mach ich in fast all meinen Anwendungen. (Im Grunde is der Backgroundworker einfach gesehn auch nur ein leichter zu konfigurierender Thread) . Wenn du es aber direkt per ThreadingClass machst, hast du den vorteil, das du die priorität des einzelnen Threads selbstständig festlegen kannst. Wie jedoch schon erwähnt wurde hat jedes Usercontrol (sprich Progressbar, etc.) einen eigenen Thread. Wenn du jedoch von einem Thread aus auf eine Property von einem Control zugreifen willst, must du einen Funktionszeiger benutzten, welche im Dot Net auch als Delegate bezeichnet werden. Mithilfe der Delegate, welche du im Thread invokest, kannst du die eigenschaften deiner Progressbar ändern und durch die auslagerung deiner funktion in einen Thread ensteht auch nicht dieser unschöne nebeneffekt, das dein Form einfriert. Lg Gateway Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Bubble Geschrieben 24. Januar 2010 Teilen Geschrieben 24. Januar 2010 (bearbeitet) Und dann bastelst du ewig daran, die Seiteneffekte abzufangen, obwohl es mit dem BackgroundWorker im Endeffekt schneller und sauberer gewesen wäre. Ich bastel daran bestimmt nicht ewig, so viele Seiteneffekte sind es gar nicht. Insbesondere in diesem Anwendungsfall, denn das GUI soll während der Verarbeitungsphase scheinbar gar keine Eingaben annehmen. Da reicht ein einzelner Thread im Prinzip aus. Und auch die Verwendung mehrerer Threads befreit einen auch nicht automatisch von allen möglichen Problemen. Bearbeitet 24. Januar 2010 von Bubble Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 24. Januar 2010 Teilen Geschrieben 24. Januar 2010 Und auch die Verwendung mehrerer Threads befreit einen auch nicht automatisch von allen möglichen Problemen. Im Prinzip läuft es darauf hinaus, ob man seinen Code lieber reentrant oder threadsafe machen möchte. Beides ist nicht ohne erhebliches Nachdenken zu machen. Weder DoEvents noch Multithreading ist eine Silberkugel für solche Probleme. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
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.