Laden...

BackgroundWorker mit Invoke Blockiert GUI

Erstellt von Sclot vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.296 Views
S
Sclot Themenstarter:in
324 Beiträge seit 2007
vor 13 Jahren
BackgroundWorker mit Invoke Blockiert GUI

Ich habe jetzt ein Programm, welches mit Emails als EML Dateien aus David Tobit Exportiert.

Der Export funktioniert über die API als eingebundene DLL Funktion:


[DllImport("dvapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DVEmlFromMailItem")]
public extern static long DVEmlFromMailItem(MailItem oMailItem, StringBuilder Path);

Diese Methode ist in einer Klasse "Tobitfunktionen" untergebracht.
Ebenfalls darin steckt eine methode, welche ein Archiv Rekursiv durchläuft und dann für die Mails, die gefunden wurden einen Export mit oben genannter Funktion macht.
Nach jeder Mail wird ein Event aufgerufen, welches mir Meldungen an die GUI zurück gibt (Welche Mail da gerade exportiert wurde).

Auf meiner Form hab ich einen BackgroundWorker.
Dieser bgw ruft im DoWork() die Rekursive Methode aus der Tobitfunktionen auf.

So..
Wenn ich das direkt so mache, bekomme ich beim Export einen Fehler:

Fehler: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

So...
kurz nachgedacht (vermutlich zu kurz) und heraus kam:
Ich erzeuge mein Objekt der Tobitfunktionen Klasse in der GUI, versuche aber mit dem DoWork() den bgw darauf zuzugreifen.
Da der DoWork() rein technisch wohl ein eigener Thread ist, könnte man hier ein Delegaten bauen und dann die eigentliche Methode aus der Klasse Invoken.

Also hab ich das umgebaut:


		# region Das hier gehört alles zum DoWork()
		// Hier wird ein Delegat definiert.
		// Den Delegaten brauchen wir, weil wir aus einen fremden Thread (BGW) auf ein Objekt zugreifen wollen, welches im GUI-Thread erzeugt wurde.
		delegate void tobitfnk_eMail2eml(string Pfad);
		
		// Eine Methode, die im GUI-Thread ausgeführt wird, soll über den Delegaten aufgerufen (Invoked) werden.
		private void eMail2eml(string Pfad)
		{
			tobitfnk.worker = backgroundWorker1;
			tobitfnk.eMail2eml(Pfad);
		}

		//#####################################################
		// !!! Achtung !!! DAS GANZE DoWork() ist ein eigener Thread!!!
		void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
		{
			// In diesem Thread wollen wir die eMail2eml Methode aus dem GUI-Thread über den tobitfnk_eMail2eml Delegaten Invoken
			Invoke(new tobitfnk_eMail2eml(eMail2eml), new object[] { e.Argument.ToString() });
		}
		//#####################################################
		#endregion 

Und was passiert nun?
Ja... Der Export funktioniert. Emails werden auch angelegt - alles toll.
ABER - die GUI Blockiert jetzt komplett.
Aber nicht dieses typische "keine Rückmeldung" mehr, sondern einfach nur stumpfes blockieren, kein verschieben, kein klicken, nixx geht.
Aber ich sehe mein Änderndes Label, das über den Event aus der Rekursiven Funktion geändert wird.

So...
Weiter geforscht...
Ich melde meinen Fortschritt aus der Rekursiven Funktion wie oben geschrieben über Events, welche dann die Labels meiner Form setzen.
Dachte damit könnte es vielleicht zu tun haben.
Jetzt hat der BackgroundWorker an sich schon einen Event "ReportProgress" welchem man auch schön ein Objekt als Userstate Parameter übergeben kann.
Also Alle Events raus gebaut und die Meldung über das ReportProgress gemacht.
Ja.. nun blockiert die GUI noch mehr, weil ich nicht mal mehr eine Veränderung im label sehe, das geändert werden sollte.

Irgenwie übersteigt das jetzt alles meinen Horizont.

Kann mich da mal jmd aufklären warum das so ist?

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Sclot,

ohne dass ich alles gelesen habe, sieht mir das sehr nach [FAQ] Warum blockiert mein GUI?, Abschnitt "Die Falle" aus.

herbivore

S
Sclot Themenstarter:in
324 Beiträge seit 2007
vor 13 Jahren

Das ist... hm...
Dann müsste ich also das was der Thread wirklich macht, alles im DoWork() machen.
Aber dann bekomm ich diesen Speicherzugriffsfehler da.

Äzend 😦

5.658 Beiträge seit 2006
vor 13 Jahren

Fehler: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

Das liegt sicher nicht am BackgroundWoker, sondern an deiner externen Funktion. Funktioniert der Aufruf denn ohne BackgroundWorker wie er soll (abgesehen von der blockierten GUI)?

Weeks of programming can save you hours of planning

S
Sclot Themenstarter:in
324 Beiträge seit 2007
vor 13 Jahren

Ja, das tut er.

Was bringt mir diese Erkenntnis jetzt?

5.658 Beiträge seit 2006
vor 13 Jahren

Was bringt mir diese Erkenntnis jetzt?

Du weißt jetzt, DASS ein Speicherzugriffsfehler kommt, wenn du diese externe Methode im BackgroundWorker ausführst. Jetzt solltest du rausbekommen, WARUM das so ist. So funktioniert Fehlerbehebung nunmal.

Auf jeden Fall solltest du mal rausfinden, ob der Fehler immer kommt, wenn du die Methode in einem anderen Thread aufrufst, also auch ohne BackgroundWorker.

Woher der Fehler kommt, kann dir aber bestimmt keiner per Ferndiagnose sagen, weil wir die Funktion bzw. den Framework nicht kennen.

Weeks of programming can save you hours of planning