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
BackgroundWorker darf WPF-Form nicht verändern
Kingkook
myCSharp.de - Member



Dabei seit:
Beiträge: 70

Themenstarter:

BackgroundWorker darf WPF-Form nicht verändern

beantworten | zitieren | melden

Liebe Com,

ich für meine Form ein BackgroundWorker, der meine GUI nach und nach Transparent machen soll.Dafür habe ich ihm im Konstruktor der Klasse die nötigen Events angehängt.


                taskbarWorker = new BackgroundWorker();
                taskbarWorker.DoWork += new DoWorkEventHandler(TaskbarDoWork);
                taskbarWorker.ProgressChanged += new ProgressChangedEventHandler(TaskbarChanged);
                taskbarWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(TaskbarCompleted);

Jetzt wartet die GUI darauf, von einer anderen Klasse ein Event zu erhalten.Wenn dieses Event gefeuert wird, wird der Worker gestartet.Er arbeitet sich normal durch, aber wenn er etwas an der GUI verändern soll, kommt eine InvalidOperationException.
Woran könnte das liegen?

Hier der BGW-Code:


        private void TaskbarDoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            worker.WorkerReportsProgress = true;
            for(int _opacity = 100 ; _opacity > 0 ; _opacity--)
            {
                worker.ReportProgress(_opacity);
                System.Threading.Thread.Sleep(100);
            }
            e.Result = e.Argument;
        }

        private void TaskbarChanged(object sender, ProgressChangedEventArgs e)
        {
            Logger.InfoWrite("Changed to {0}", e.ProgressPercentage);
            float newOpacity = (float)e.ProgressPercentage;
            this.volumeBar.Opacity = newOpacity;
        }

        private void TaskbarCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Logger.InfoWrite("Completed");
        }

Danke im voraus... Kooki :-)
private Nachricht | Beiträge des Benutzers
DaMoe80
myCSharp.de - Member



Dabei seit:
Beiträge: 508

beantworten | zitieren | melden

Moin!

Schau mal hier:

[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Gruss,
DaMoe
private Nachricht | Beiträge des Benutzers
Kingkook
myCSharp.de - Member



Dabei seit:
Beiträge: 70

Themenstarter:

beantworten | zitieren | melden

Danke erstmal,
den Artikel habe ich vorher bereits gelesen aber folgenden Absatz so verstanden, dass es bei mir eigentlich gehen sollte.
Zitat
BackgroundWorker

Statt mit extra Threads und Control.Invoke, kann man auch mit der BackgroundWorker-Klasse ungültige threadübergreifende Vorgänge vermeiden. Dazu müssen bei BackgroundWorker alle Zugriffe auf das GUI einfach aus den ProgressChanged- oder RunWorkerCompleted-EventHandlern durchgeführt werden. Wenn man sich daran hält, ist explizites Control.Invoke bei BackgroundWorker nicht erforderlich, denn die genannten EventHandler werden hinter den Kulissen automatisch per Control.BeginInvoke aufgerufen.

Alles vorausgesetzt, der BackgroundWorker wurde korrekt initialisiert, so dass er insbesondere einen passenden SynchronizationContext verwendet. Wenn der BGW unter Verwendung von VS im GUI-/Main-Thread erzeugt wurde, sollte das automatisch der Fall sein.

Meiner Meinung nach sollte es doch bei mir funzen, wenn der BGW bei Erstellung der WPF-Form initialisiert wird, und Events angehängt bekommt.Da ich die GUI-Manipulation erst im Changed Event ausführe, sollte doch alles stimmen oder?
private Nachricht | Beiträge des Benutzers
DaMoe80
myCSharp.de - Member



Dabei seit:
Beiträge: 508

beantworten | zitieren | melden

Hi Kingkook!

Es sollte automatisch funtionieren, wenn Du den BackgroudWorker im UI Thread erstellst. Das ist wichtig, dam der BGW bzw. der SynchronizationContext im BGW erkennt, ob zwischen den Threads "geswitcht" werden muss.
Zitat
Jetzt wartet die GUI darauf, von einer anderen Klasse ein Event zu erhalten.Wenn dieses Event gefeuert wird, wird der Worker gestartet.

In welchem Thread wird der BGW initialisiert?

By the way: Du brauchst in der Methode TaskDoWork nicht immer das Property WorkerReportsProgress auf true setzen. Das genuegt initial einmal bei Erstellung des BGW.

Gruss,
DaMoe
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10083

beantworten | zitieren | melden

@Kingkook:
Sobald Thread.Sleep im BGW zum Einsatz kommt, ist es meist die falsche Herangehensweise.

Für diese simple Funktion mit Threading zu arbeiten ist nicht nötig.
Erstelle einen Forms.Timer und mache das dadrin.

Und die Exception bekommst du weil du nicht geschaut hast welche Wertebereiche Opacity hat.
private Nachricht | Beiträge des Benutzers
Kingkook
myCSharp.de - Member



Dabei seit:
Beiträge: 70

Themenstarter:

beantworten | zitieren | melden

@DaMoe80

Initialisiert wird er, wenn auch das WPF-Fenster initialisiert wird, jedoch wird er wie gesagt in einer Methode gestartet, welche von einem Event aufgerufen wurde.

@FZelle

Mit einem Timer habe ich es vorher getestet, hat aber nicht funktioniert :-(
Mit dem Wertebereich kann es aber nichts zu tun haben, der wird erstens eingehalten und ausserdem funktioniert die ganze BGW Geschichte auch, wenn ich zB direkt bei der Initialisierung RunWorkerAsynch() aufrufe.Nur wenn ich diesen Startin einem Event aufrufe, kommt die Fehlermeldung...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Kingkook am .
private Nachricht | Beiträge des Benutzers
Briefkasten
myCSharp.de - Member

Avatar #avatar-1523.gif


Dabei seit:
Beiträge: 444

beantworten | zitieren | melden

Hallo,

du könntest auch probieren das Fenster mit einer Animation langsam transparent zu machen.
Schaut mal im IRC vorbei:
Server: [email protected]#c#.de oder [email protected]#csharp
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10083

beantworten | zitieren | melden

Zitat
Mit dem Wertebereich kann es aber nichts zu tun haben, der wird erstens eingehalten
Da Opacity ein Float im bereich 0-1 ist, kann das nicht sein.
Zitat
Mit einem Timer habe ich es vorher getestet, hat aber nicht funktioniert :-(
Dann hast du nicht den richtigen Timer genommen, gibt da nämlich 3 von.
Und funktioniert nicht ist keine vernünftige Fehlerbeschreibung.
Zitat
.Nur wenn ich diesen Startin einem Event aufrufe, kommt die Fehlermeldung...
Dann hast Du uns verschwiegen aus was für einem Event das kommt.
private Nachricht | Beiträge des Benutzers