eigene ImageChooser-Komponente funktioniert nur alleine - BackgroundWirker!
-
C. M. Obrecht schrieb:
Der Code funktioniert bis zum Aufruf der Backgroundworker-Komponente, führt diesen aber nicht aus (Debugger kehrt zurück).
backgroundWorker1.RunWorkerAsync();
Wenn Du damit meinst das RunWorkerAsync() sofort zurückkehrt dann ist das zu erwartendes Verhalten. RunWorkerAsync bedeutet genau das: Der Aufruf wird nur asynchron gestartet, aber der aktuelle Thread arbeitet sofort weiter.
Der Background-Thread ist ja, wie der Name sagt, ein separater Thread. Der debugegr wechselt nicht automatisch in andere Threads, ausser Du setzt da zusätzliche Breakpoints.
C. M. Obrecht schrieb:
foreach (Control c in flowLayoutPanel1.Controls) { FileInfo f = myfileinfos[index] as FileInfo; PictureBox pictbox = c as PictureBox; pictbox.SizeMode = PictureBoxSizeMode.Zoom; pictbox.Size = new Size(80, 60); pictbox.BorderStyle = BorderStyle.Fixed3D; pictbox.Tag = f.FullName; pictbox.LoadAsync(f.FullName); pictbox.DoubleClick += new EventHandler(picboxeventhandler); toolStripProgressBar2.Value = index; index++; } } catch (Exception ex) { } }
Das nennt man Error-Hiding. NIEMALS einfach nur alle Exceptions fangen und dann nichts tuen, so siehst Du den eigendlichen Fehler hier nicht.
Du greifst aus einem anderen Thread auf Componenten der Form zu (Controls). Leider ist Windows-Forms aber Single-Threaded und man darf nicht aus anderen Thread heraus auf Elemente der Form zugreifen. Hier wird eine Cross-Thread exception geworfen die Du aber durch den leeren catch "versteckst".
-
Wie stellt man den Debugger ein dass er bei Ausnahmen erster Chance hält?
Ach so, der Debugger springt gar nicht in andere Threads; das vermutete ich irgendwie noch. Habe bei dieser Zeile, vor dem BackgroundWorker-Aufruf folgende Ausgaben erhalten:bei: flowLayoutPanel1.Controls.Clear(); "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c561934e089\System.Windows.Forms.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sync\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "C:\Daten\netBildbearbeitungsprogramm\netBildbearbeitungsprogramm\bin\Debug\netBildbearbeitungsprogramm.vshost.exe" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\mscorlib.resources\2.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Deployment\2.0.0.0__b03f5f7f11d50a3a\System.Deployment.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System.Xml.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert. Der Thread '<Kein Name>' (0xe60) hat mit Code 0 (0x0) geendet. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "C:\Daten\netBildbearbeitungsprogramm\netBildbearbeitungsprogramm\bin\Debug\netBildbearbeitungsprogramm.exe" geladen, Symbole geladen. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms.resources\2.0.0.0_de_b77a5c561934e089\System.Windows.Forms.resources.dll" geladen, keine Symbole geladen. Eine Ausnahme (erste Chance) des Typs "System.IndexOutOfRangeException" ist in netBildbearbeitungsprogramm.exe aufgetreten. "netBildbearbeitungsprogramm.vshost.exe" (Verwaltet): "F:\WINDOWS\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll" wurde geladen, das Laden von Symbolen wurde übersprungen. Das Modul ist optimiert, und die Debugoption "Nur mein Code" ist aktiviert.
danach verbleibt der Debugger ständig in
private void pictureBox1_Paint(object sender, PaintEventArgs e) { if (_selecting) { Pen pen = Pens.GreenYellow; e.Graphics.DrawRectangle(pen, _selection); }
ich frage mich ob das normal ist dass die PictureBox (also die im Hauptfenster, nicht in dem ImageChooser-Form) ständig Paint-Nachrichten erhält?
Klar wegen dem Errorhandling; ich habe diesen Try/Catch kurz eingefügt wegen möglichen OutOfMemoryExceptions (ist noch nicht alles fertig); klar auch dass dies Exceptions versteckt. Aber warum funktioniert der Code wie er ist als eigenstehende .exe? Auf die Controls von ImageChooser wird nur in den entsprechenden Ereignishandlern zugegriffen, nie aus dem BackgroundWorker-Thread...
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string lookfor = "*.bmp;*.tiff;*.tif;*.png;*.gif;*.jpg;*.jpeg;*.wmf;*.emf"; string[] extensions = lookfor.Split(new char[] { ';' }); DirectoryInfo di = new DirectoryInfo(folderBrowserDialog1.SelectedPath); foreach (string ext in extensions) { myfileinfos.AddRange(di.GetFiles(ext, opt)); int percentage = toolStripProgressBar1.Value + 10; if (percentage > 100) percentage = 100; backgroundWorker1.ReportProgress(percentage); if (backgroundWorker1.CancellationPending) break; } }
-
STRG + ALT + E und da das gewünschte Anhaken.
OutOfMemoryExceptions
Ich setze in der Endanwendungssoftware (letzte Schicht) auch gern mal ein TryCatch Block. Aber wenn man nur eine OutOfMemoryExceptions fangen möchte dann sollte man das auch tun. (Das Risiko eines TryCatch hat Looks ja bereits erläutert. Man schadet sich damit i.d.R. mehr als man nutzen zieht.)
catch(OutOfMemoryExceptions ex){}
danach verbleibt der Debugger ständig in
Heißt er hängt da oder er springt da immer wieder rein ?! (Beachte: wenn Dein Debugger das Programmfenster verdeckt und Du dann vom Debugger zum Fenster wechselst, alles neu gezeichnet werden muss.)
-
Ich habe nun alle Exceptions aktiviert aber es ist keine aufgetreten; ausser beim Start des Programes eine IndexOutOfRange-Exception da ich keine Kommandozeilenargumente angegeben habe (normal wenn das Programm gestartet wird ohne gleich eine Datei zum öffnen anzugeben).
Sehr eigenartig! Der Debugger bleibt in der Paint-Methode, aber ohne dass ich zum Programmfenster wechselte. Glaube aber nicht dass dies wirklich mit dem Problem zu TUn hat.
Der BackgroundWorker funktioniert normalerweise ja schon in Fenstern die mit ShowDialog() aufgerufen wurden!? Mir kommt es so vor als wäre das ein Problem.
-
Wenn er da hängt und es nicht weiter geht kann es auch einfach ein Deadlock sein. Lässt sich so schwer sagen. Kapsel mal die UI Zugriffe ordentlich weg und achte auf Deadlocks.
-
Vielen Dank, ja das könnte ich mir noch vorstellen; solche Deadlocks sind ja schwierig zu finden wenn sie innerhalb von Funktionen des Frameworks auftreten. Aber würde das Programm noch reagieren bei einem Deadlock? Der Abbrechen-Button funktioniert bzw. das Fenster kann ich schliessen und die Anwendung funktioniert dann normal weiter.
-
Jain, das hängt davon ab ob der GUI Thread am Deadlock beteiligt ist. Wenn ja reagiert garnichts mehr. Was bei Dir klemmt lässt sich so aber nicht sagen. IMHO sind die Informationen rund um zu wenig.
-
Hmm es muss kein GUI-Thread beteiligt sein, da die Fenster jeweils ja reagieren.
Habe nichts weiter herausfinden können. Hier wäre mal der gesamte Quellcode: http://rebenstudio-it.ch/QuellcodenetBildbearbeitungsprogramm.zip
-
Trag einfach die Methode backgroundWorker1_DoWork im Backgroundworker ein und schon wird die Methode auch aufgerufen.
-
mmmh so einfach. Die müssen beim einfügen des Fensters in das Projekt rausgefallen sein. Und das habe ich doch nicht angeschat. Danke
Weisst Du (oder sonst jemand) da zufällig gleich wie ich beim "umwandeln in 256 Farben" Dithering mit einbeziehen kann? Es wird zwar durch den OctreeQuantizer eine gute Palette erzeugt, aber da keine Fehlerstreuung eingesetzt wird sehen die Bilder etwas wie Gemälde aus...
-
Nein, aber es wäre eine gute Idee einen neuen Thread zu eröffnen. Eventuell sogar im "Spiele und Grafikforum" . Mag dann zwar nicht gleich in C# enden, aber wertvoll könnten die Tips sein.
-
Habe ich getan
Vielen Dank