Laden...

Threading-Problem

Erstellt von DavidT vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.138 Views
DavidT Themenstarter:in
998 Beiträge seit 2007
vor 16 Jahren
Threading-Problem

Hallo,

ich habe ein kleines Threadproblem und bekomme es irgendwie nicht gelöst.

Ich habe eine Klasse mit einem Feld Image und 2 Methoden.

Hier mal ein vereinfachtes Beispiel.


public class ImageViewer
{
   private Image img;

   private void WorkerThread1(Image muh)
   {
       img = muh;
   }

   private void WorkerThread2()
   {
       pictureBox = img;
   }
}


Nun greifen 2 Threads auf ein Objekt der Klasse zu. Thread 1 auf WorkerThread1 und Thread2 auf WorkerThread2.

Nun bekomme ich das Problem, dass manchmal in der PictureBox ein Bild dargestellt wird, was halb abgeschnitten ist.
Offensichtlich ist es so, das Thread1 noch das Bild in das Feld schreibt und Thread2 schon mit dem auslesen beginnt.

Soetwas wann man scheinbar mit Semaphoren hinbekommen, aber ich scheine ganz offensichtlich zu blöd dafür zu sein.

Kann mir da wer helfen?

Danke, David

343 Beiträge seit 2007
vor 16 Jahren

Nun bekomme ich das Problem, dass manchmal in der PictureBox ein Bild dargestellt wird, was halb abgeschnitten ist.
Offensichtlich ist es so, das Thread1 noch das Bild in das Feld schreibt und Thread2 schon mit dem auslesen beginnt.

Nun wenn es wirklich daran liegt, solltest du in einer Variable speichern, wenn das Bild fertig ist und Thread2 darf dann erst mit dem Lesen beginnen.
Wenn diese Dinge hintereinander passieren stellt sich jedoch wieder die Frage wozu man dann überhaupt zwei Threads braucht und ob man das nicht in einem unterbekommt.

Mfg Preli

[- www.saftware.net -](http://www.saftware.net/)
DavidT Themenstarter:in
998 Beiträge seit 2007
vor 16 Jahren

Da das Bild später in einer PictureBox dargestellt wird, kann ich leider nicht aus Thread2 Invalidate() aufrufen, da das nur der Thread darf, der die PictureBox erstellt hat und das ist nurmal Thread1...

343 Beiträge seit 2007
vor 16 Jahren

Invoke bzw. InvokeRequired können dir da sicherlich weiterhelfen.
Damit kann man auch auf GUI-Elemente anderer Threads zugreifen.

Google mal danach oder lies in der MSDN nach, ist eine sauberere, schnellere und bessere Lösung

Mfg Preli

[- www.saftware.net -](http://www.saftware.net/)
DavidT Themenstarter:in
998 Beiträge seit 2007
vor 16 Jahren

Jo richtig, mit Invoke arbeite ich auch. Durch die pictureBox kann ich es nur mit 2 Threads machen.
Wenn ich nun aber eine Funktion implementiere um das Bild per "Speichern unter..." in eine Datei zu schreiben, passiert es manchmal, das er grade das Bild abspeichert was geschrieben wird.

Das ist es was ich verhindern möchte.

343 Beiträge seit 2007
vor 16 Jahren

Verstehe, dann solltest wie ich oben schon geschrieben habe eine Variable nehmen, die angibt, ob das Bild nun "bereit zum Speichern" ist oder nicht.
Evt. ließe sich auch mit "lock" arbeiten, kommt auf den Geschmack und das Beispiel drauf an.
Bei devtrain.de gibts einen (meiner Meinung nach) guten Artikel zum Thema lock und Threading: http://www.devtrain.de/artikel_790.aspx
Oder sonst lock-Anweisung bei MSDN: http://msdn2.microsoft.com/de-de/library/c5kehkcz(VS.80).aspx

Mfg Preli

PS: Vielleicht gäbs auch noch eine bessere Lösung, aber so würde ich es machen, wenn jemand noch weitere Ideen hat, dann nur raus damit.

[- www.saftware.net -](http://www.saftware.net/)
DavidT Themenstarter:in
998 Beiträge seit 2007
vor 16 Jahren

Hey,

danke zunächst für deine Hilfe, denke das "lock" genau das richtige für mich ist, vielen Dank 🙂

Gruß David

U
17 Beiträge seit 2005
vor 16 Jahren

Hi,

generell solltest Du in solchen Fällen das ganze mit Mutex absichern.

private Mutex myMutex = new Mutex();

Dann kann kein weiterer Thread in Deiner Methode etwas unternehmen so lange diese nicht verlassen wurde.

 
          try
            {
               myMutex.WaitOne();

               // Dein Code
            }
            catch
            {
                ;
            }
            finally
            {
                myMutex.ReleaseMutex();
            }

Auf "WaitOne" wird gewartet bis der "ReleaseMutex" gemeldet wurde. So kannst Du auch mehrere Methoden innerhalb der Klasse gegenseitig absichern.

Vll. hilft Dir das weiter - kann bei Bedarf auch ein komplettes Beispiel liefern 😁

DavidT Themenstarter:in
998 Beiträge seit 2007
vor 16 Jahren

Genau an sowas dachte ich Uwe 🙂 Ich hatte aber noch irgendwas mit Semaphoren im Kopf, aber das geht ja scheinbar auch!

Danke

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo DavidT,

musst bei der Synchronisation aber aufpassen, dass sichergestellt ist, dass dein GUI-Thread nicht zu lange warten muss, denn sonst bekommst du das Problem, dass in [FAQ] Warum blockiert mein GUI? beschrieben ist.

Es kann sein, dass das mit Semaphoren (also mit blockierendem Warten) nicht zu gewährleisten ist. In diesem Fall solltest du Events in Betracht ziehen.

herbivore

R
402 Beiträge seit 2005
vor 16 Jahren

hi,wollte mal kurz fragen wo jetzt der Unterschied zwischen einer Mutex-Variable und Montitor.Enter/Lock liegt,abgesehen daven,dass man Mutex-Variablen auch für Interprozesskommunikation nutzen kann!!
gibt es eine regel wann was(mutex oder Montior.Enter/Lock) zu benutzen ist???

danke schön

lg rizi

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo rizi,

naja, es gibt eine ganze Reihe von Unterschieden. So steht in der Mutex-Klasse mit mit WaitAll oder WaitAny eine Möglichkeit zur Verfügung, die die Monitor-Klasse einfach nicht bietet. Einen weiteren Unterschied, hast du schon genannt, nämlich das Monitor auf Synchronisation innerhalb eines Prozesses beschränkt ist. Außerdem ist Monitor (im Prinzip) eine statische Klasse, während man von Mutex Instanzen erzeugen kann und muss. Insgesamt ist Monitor die simplere und einfachere Klasse und Mutex bietet weitergehende Möglichkeiten. Der grundlegende Zweck ist aber bei beiden gleich.

Monitor würde ich möglichst nicht direkt benutzen, sondern stattdessen immer nur lock, das ja auf der Monitor-Klasse basiert. Und Mutex, wenn die Funktionalität von Monitor bzw. lock nicht ausreicht.

herbivore

R
402 Beiträge seit 2005
vor 16 Jahren

danke dir herbie!!

lg rizi