Hallo,
altes Spiel: Ich führe einen aufwendigen Prozess aus, möchte dabei aber den GUI weiterhin arbeiten lassen. Also nehme ich mir den BGW und lagere alles soweit aus. Trotzdem hab ich jetzt das Problem, dass der GUI sich nach Abschluss des BGW über den RunWorkerCompleted nicht korrekt neuzeichnet. Blockieren tut der GUI zunächst nicht, er zeichnet Controls beim Darüberbewegen mit der Maus sogar neu. Aber nach wenigen Sekunden blockiert dann alles, ironischerweise zeichnet sich sogar die Taskbar von Windows Vista falsch und überlappt. Beim Öffnen des Kontaktmenüs in der Taskleiste schmiert die Anwendung dann still und heimlich ab, keine Meldung, keine Ahnung. Debug hat nicht viel gebracht, denn die Events des BGW laufen alle sauber durch und beim Pausieren danach zeigt er nur auf Application.Run(...). Irgendwie hab ich das Gefühl, dass der BGW nicht vollständig verarbeitet wird. 😭
Mit freundlichen Grüßen,
pogo
PS: Es handelt sich bei dem "aufwendigen Prozess" eigentlich nur um das Auslesen eines gewählten Verzeichnisses samt Unterverzeichnisse. Und nein, DoEvents() wurde nicht benutzt. 😉
und beim Pausieren danach zeigt er nur auf Application.Run(...)
falscher thread (nicht im forum sondern in deiner applikation 😉 )?
wenn deine UI dennoch darstellungsfehler hat, dann hast du etwas falsch gemacht. evtl unterbrichst du sie zu häufig, das sie keine zeit hat sich zu rendern?
zeig mal code (nur den relevanten)
private void GetFiles(string directory, bool subDirectories)
{
if (working) return;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(GetFilesWorking);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(GetFilesWorkerCompleted);
if (!worker.IsBusy)
{
SetProgress("Getting files of the selected directory...", true);
imageListIcons.Images.Clear();
worker.RunWorkerAsync(new object[] { directory, subDirectories });
}
}
private void GetFilesWorking(object sender, DoWorkEventArgs e)
{
object[] arguments = (object[])e.Argument;
string directory = (string)arguments[0];
bool subDirectories = (bool)arguments[1];
if (directory.Length <= 0) return;
BackgroundWorker worker = sender as BackgroundWorker;
List<ListViewItem> items = new List<ListViewItem>();
try
{
string[] files = Directory.GetFiles(directory);
foreach (string file in files)
{
FileInfo info = new FileInfo(file);
imageListIcons.Images.Add(file, Program.GetIcon(file));
ListViewItem item = new ListViewItem(new string[] { Program.CutFileExtension(info.Name), String.Empty, info.Extension.Replace(".", String.Empty).ToUpper(), Program.CovertBytesToUnit(info.Length) }, file);
item.Tag = file;
items.Add(item);
}
}
catch { }
if (subDirectories)
{
try
{
string[] folders = Directory.GetDirectories(directory);
foreach (string folder in folders)
{
GetSubFiles(folder, items);
}
}
catch { }
}
e.Result = items.ToArray();
}
private void GetFilesWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
listViewFiles.BeginUpdate();
listViewFiles.Items.Clear();
listViewFiles.Items.AddRange((ListViewItem[])e.Result);
listViewFiles.EndUpdate();
SetProgress("Ready", false);
}
private void GetSubFiles(string directory, List<ListViewItem> items)
{
try
{
string[] files = Directory.GetFiles(directory);
foreach (string file in files)
{
FileInfo info = new FileInfo(file);
imageListIcons.Images.Add(file, Program.GetIcon(file));
ListViewItem item = new ListViewItem(new string[] { Program.CutFileExtension(info.Name), String.Empty, info.Extension.Replace(".", String.Empty).ToUpper(), Program.CovertBytesToUnit(info.Length) }, file);
item.Tag = file;
items.Add(item);
}
}
catch { }
try
{
string[] folders = Directory.GetDirectories(directory);
foreach (string folder in folders)
{
GetSubFiles(folder, items);
}
}
catch { }
}
Du greifst aus dem DoWork-Event auf Controls zu. Das darf man niemals tun!
Außerdem wäre es vllt. für die Performance gut das Ergebnis zu puffern und nur alle 25 gefundenen Dateien das GUI zu aktualisieren.
Grüße, JasonDelife.
Beim Programmieren löst man die Probleme, die man nicht hätte, programmierte man nicht.
Stimmt, die ImageList habe ich vergessen auszulagern, aber das ist leider nicht das Problem.
Den GUI aktualisiere ich gar nicht permanent. Ganz im Gegenteil, der GUI bekommt erst am Ende des BGW die Daten in das Control (ListView) übermittelt.
Edit: Ich muss gerade feststellen, dass dieser Zeichenfehler auch ohne BGW vorkommt. Seltsam, könnte das etwas mit Vista zu tun haben?
Wer so welchen Code schreibt:
try
{
// tue irgendwas
}
catch { /* tue nichts */ }
Dem kann man eiglich nicht helfen.
Das unterdrückt jede Fehlermeldung, du kannst also schon prinzipiell keinen Plan haben, was schief läuft.
Die Fehler, die du mitbekommst, _können _"echte" Fehler sein, sind aber wahrscheinlicher Folge-Fehler von Fehlern, die nicht gemeldet wurden - das kann man nicht wissen.
was soll man dir da raten? Deine Fragen haben höchstwahrscheinlich keinen Bezug zum Problem.
Der frühe Apfel fängt den Wurm.
Klasse Kommentar. Hirn ausschalten und einfach mal arrogant drauf losmotzen.
Die IO/Access-Exceptions fange ich natürlich im Catch-Block ab, das sieht man bloß nicht, weil ich die Catches auf { } minimiert habe (der Codeausschnitt ist ohnehin schon so groß). Tu' mir einen Gefallen und drück das große X oben rechts, du bist mir schon mehrfach negativ aufgefallen. Deine Hilfe möchte ich nicht, ErfinderDesRades. Danke für dein Verständnis.
Der Einwand von ErfinderDesRades war absolut gerechtfertigt... man sieht Deinem Code nicht an, dass Du in den Catches was drin hast...
Und vorallem Umsteiger von VB (nicht .Net) haben in VB mit On error resume next gearbeitet und machen dann in .Net leere Catches...
@pogo nicht gleich beleidigt sein... sonst drücke ich das noch grössere Y und mache hier zu. 😉
Gruss
Programmierhans
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
Hallo pogo
Ich bin mir jetzt nicht sicher, aber viell. hat's mit der ImageList zu tun. Das ist einer der Komponenten die 1:1 Win32 wrappen. Du fügst für jede Datei ein Item in die Liste hinzu. Wenn die Ordnerstruktur tief ist kann ich mir vorstellen dass Windows ein Problem bekommt intern die ganzen Handles zu verwalten. Versuch' hier mal zu optimieren. Eigentlich musst du nur die Bilder für Extensions wie ".exe", ".ico" und noch ein paar wirklich pro Datei holen für die restlichen Dateien wie ".txt" oder ".doc" reicht eine Referenz die für alle ListViewItems verwendet werden kann.
Grüße
Flo
Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+
Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.
@pogo:
Sorry, die Bemerkung hättich in dieser Form vlt. auch sparen können.
Ansonsten kann ich den Code ja nur nehmen, wie er da steht, und leere Catches sind in meinen Augen tatsächlich absolutely No-Go. Das habich mit der gleichzeitig passenden und unpassenden Bemerkung ausgedrückt:
Dem kann man eiglich nicht helfen.
Unpassend, weil ähnelt dem abfälligem Ausdruck "dem kann man nicht mehr helfen", aber ähnelt nur.
Passend, weil ist inhaltlich und wörtlich korrekt: bei Code mit leeren Catches kann man wirklich nicht helfen, da prinzipiell un-debug-bar. Habe ich ja auch differenziert begründet, war also nicht nur Motze.
Naja, ich gelobe Besserung, und dich lass ich fürderhin auch in Ruhe mit meine Kommentare.
Der frühe Apfel fängt den Wurm.