Ich habe gerade das Problem, dass ich einer ListView Bilder bereitstellen will, die möglichst nur bei Bedarf (wenn sie auch gezeichnet werden müssen) geladen werden, aber das ohne das gesamte Interface zu blockieren.
Daher muss zum Laden der Bilder (und Skalieren auf die passende Größe) ein zweiter Thread her. Grundsätzlich hatte ich dafür mittlerweile alles Notwendige eingebaut, allerdings wird mir bei e.Graphics.DrawImage im folgenden Beispiel "ArgumentException" gesagt, wozu ich überhaupt keine Erklärung habe.
Weiß jemand, wo hier das Problem ist, das diese ArgumentException verursacht? Der Code der oberen Methode klappt definitiv, nur nicht, wenn ich ihn über den Delegaten aus dem zweiten Thread aufrufe.
Alternativ: Wie könnte man sonst realisieren, dass die Bilder in einem zweiten Thread geladen werden und jedes fertig geladene Bild sofort gezeichnet wird? Das Kriterium ist hier auf jeden Fall, dass das Interface dauerhaft nutzbar bleibt.
Danke für eure Hilfe
Daher muss zum Laden der Bilder (und Skalieren auf die passende Größe) ein zweiter Thread her. Grundsätzlich hatte ich dafür mittlerweile alles Notwendige eingebaut, allerdings wird mir bei e.Graphics.DrawImage im folgenden Beispiel "ArgumentException" gesagt, wozu ich überhaupt keine Erklärung habe.
Code:
void DrawMethod(DrawListViewItemEventArgs e)
{
Image abc = Image.FromFile(gültigerBildPfad);
e.Graphics.DrawImage(abc, e.Bounds.Location); //"Argument Exception"
}
void DrawLoader()
{
while (true)
{
DrawDelegate dd = new DrawDelegate(DrawMethod);
while (queue.Count > 0) //queue enthält ListViewDrawItemEventArgs-Objekte, die genau so von der ListView erzeugt wurden
{
float scale = 1;
DrawListViewItemEventArgs DLVIEA;
lock (this)
{
DLVIEA = (DrawListViewItemEventArgs)queue.Dequeue();
}
if (!ImageLoad[DLVIEA.ItemIndex]) //ImageLoad ist ein bool-Array, welches speichert, ob das Bild bereits geladen wurde
Img[DLVIEA.ItemIndex] = Image.FromFile(ImagePaths[DLVIEA.ItemIndex]);
if (!ImageScaled[DLVIEA.ItemIndex]) //ImageScaled ist ein bool-Array, welches speichert, ob das Bild bereits passend skaliert wurde
{ //Der folgende Abschnitt ist egal, da er lediglich für die Skalierung des Bildes sorgt
if (Img[DLVIEA.ItemIndex].Width >= Img[DLVIEA.ItemIndex].Height && Img[DLVIEA.ItemIndex].Width > ImageSize)
{
scale = (float)Img[DLVIEA.ItemIndex].Width / (float)ImageSize;
}
else
if (Img[DLVIEA.ItemIndex].Height > ImageSize)
{
scale = (float)Img[DLVIEA.ItemIndex].Height / (float)ImageSize;
}
Img[DLVIEA.ItemIndex] = new Bitmap(Img[DLVIEA.ItemIndex], (int)(Img[DLVIEA.ItemIndex].Width / scale), (int)(Img[DLVIEA.ItemIndex].Height / scale));
}
lv.Invoke(dd, DLVIEA); //An dieser Stelle wird die obere Methode aufgerufen
}
Thread.Sleep(100); //Überprüft alle 100 ms, ob etwas neues geladen werden muss. Ich habe das so gelöst, weil es deutlich einfacher als eine richtige Synchronisation ist und praktisch keine Ressourcen verbraucht
}
Alternativ: Wie könnte man sonst realisieren, dass die Bilder in einem zweiten Thread geladen werden und jedes fertig geladene Bild sofort gezeichnet wird? Das Kriterium ist hier auf jeden Fall, dass das Interface dauerhaft nutzbar bleibt.
Danke für eure Hilfe