2016-05-23 5 views
2

Ich habe eine winforms-Anwendung, bei der der Benutzer ein Bild aus einer Liste verfügbarer Bilder auswählen kann und das entsprechende Bild in einer PictureBox angezeigt wird. Die Bilder können mit mindestens 10 MB sehr groß sein. Dies führt offensichtlich dazu, dass der Rest der Benutzeroberfläche nicht mehr reagiert, während das Bild geladen wird. So dachte ich auf einem separaten Thread das Bild des Beladens mit dem folgenden Code:PictureBox zugewiesen ErrorImage wird nicht angezeigt, nachdem das Bild falsch sortiert wurde

private void LoadImage() 
{ 
    // loadViewerThread is a Thread object 
    if (loadViewerThread != null && loadViewerThread.IsAlive) 
    { 
     loadViewerThread.Abort(); // Aborting the previous thread if the user has selected another image 
    } 
    loadViewerThread = new Thread(SetViewerImage); 
    loadViewerThread.Start(); 
} 

Die SetViewerImage Funktion ist wie folgt:

private void SetViewerImage() 
{ 
    if (pictureBox1.Image != null) 
     pictureBox1.Image.Dispose(); 
    pictureBox1.Image = new Bitmap(/*Some stream*/); 
} 

Danach werden die Bilder laden glatt und die UI kann auch zugegriffen werden, . Wenn sich der Benutzer jedoch sehr schnell zwischen den Bildern bewegt, wird ein großes rotes X angezeigt. Dies passiert, weil ich diesen Anruf an Dispose in SetViewerImage habe.

Ich habe der PictureBox ein ErrorImage zugewiesen, aber dieses ErrorImage wird in diesem Fall nie angezeigt.

Fragen:

  1. Gibt es etwas falsch mit meiner Thread-Implementierung? Warum wird das Image entsorgt?
  2. Gibt es eine Möglichkeit, dass ich ein anderes ErrorImage und nicht das rote X anzeigen kann?
+0

Durch allgemeine Vereinbarung die sicherste Art und Weise eines Verfügungs 'pb.Image' ist das:' if (...) {Image temp = pictureBox1.Image; BildBox1.Image = null; temp.Dispose(); } 'Nicht sicher, ob es hilft, aber es ist ein erster Schritt zu machen .. - Auch: Sie haben die 'InitialImage'-Eigenschaft bemerkt, ja? - Und schließlich: Sie können die Liste einfach deaktivieren, bis das Bild vollständig geladen ist. – TaW

+0

Wenn Sie die Image-Eigenschaft auf null setzen, ist die Bildbox leer und zeigt nicht das benutzerdefinierte ErrorImage an. Ich kann die Liste der Bilder nicht deaktivieren. In meinem Fall sollte es dem Benutzer erlaubt sein, sich zwischen den Bildern zu bewegen. –

+0

_Beim Setzen der Image-Eigenschaft auf null ist die Bildbox leer und zeigt nicht die benutzerdefinierte ErrorImage._ Natürlich, warum sollte es? Null ist kein Fehler, nur ein leerer PB. Auch wenn Sie die Liste nicht deaktivieren möchten, würde ich versuchen, jeden laufenden Thread zu deaktivieren/abzubrechen, wenn ein neues Bild ausgewählt wurde, bis das ImageLoaded-Ereignis erreicht wurde. – TaW

Antwort

0

Sie müssen Steuerelemente im UI-Thread bearbeiten. Sie können dies tun, indem Sie Control.Invoke() aus einem anderen Thread verwenden.

Der große Engpass schafft das Bild aus dem Strom, so sollten Sie in der Lage sein, Ihre Methode so reorganisieren der UI-Thread zu halten freigegeben:

private void SetViewerImage() 
{ 
    Bitmap image = new Bitmap(/* Some stream*/); 

    pictureBox1.Invoke(new Action(() => 
     { 
      if (pictureBox1.Image != null) 
      { 
       pictureBox1.Image.Dispose(); 
       pictureBox1.Image = null; // This might help? Only add if it does. 
      } 
      pictureBox1.Image = image; 
     })); 
} 
+0

@itseme Ich wollte die Frage nicht zu sehr komplizieren, deshalb habe ich den Aufruf von Invoke nicht gepostet. Da ich die Manipulationen an einem Diff-Thread mache, habe ich das benutzt. Ich habe Ihren Vorschlag ausprobiert, Image auf null zu setzen. Es zeigte nicht das rote X, aber die Bildbox war leer. Es zeigte das benutzerdefinierte ErrorImage nicht an –

Verwandte Themen