1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Thread: Das Objekt wird bereits an anderer Stelle verwendet

Dieses Thema im Forum ".NET" wurde erstellt von Halfbax, 17. März 2017.

  1. Halfbax

    Halfbax Erfahrenes Mitglied

    Guten Abend,

    seitdem ich einen Speicherleak behoben habe. Steht die Funktionalität meines Programms auf der Kippe. Ich bin gerade dabei einen Mandelbrot Generator zu erstellen und nutze dafür Threads.

    Das Problem tritt nun auf, wenn das MouseMove Event getriggert wird, denn dann wird der jeweilige Thread mehrmals aufgerufen, wobei der alte Thread noch nicht beendet ist. Selbst ein Thread.Abort() hilft mir nicht. Desweiteren wird mein Viereck nicht mehr richtig gezeichnet.

    FractalWindow.cs
    Code (C#):
    1.         private void imagePanel_MouseMove(object sender, MouseEventArgs e)
    2.         {
    3.             if(e.Button == MouseButtons.Left)
    4.             {
    5.                 renderThread.Abort();
    6.                 renderThread = new Thread(delegate () {
    7.                     fractalHandler.RenderMouseEvent(new Point(e.X, e.Y), pStart);
    8.                 });
    9.  
    10.                 renderThread.Start();
    11.  
    12.                 imagePanel.BackgroundImage = (Image) fractalHandler.getDataSource();
    13.             }
    14.         }
    Code (C#):
    1. public void RenderMouseEvent(Point e, Point pStart)
    2.         {
    3.             if (datasource != null)
    4.             {
    5.                 datasource = Fractal.generateRectangleOnBitmap(datasource, panelWidth, panelHeight, e, pStart);
    6.             }
    7.         }
    Code (C#):
    1.         public static Bitmap generateRectangleOnBitmap(Bitmap datasource, int panelWidth, int panelHeight, Point e, Point pStart)
    2.         {
    3.             Point temp = new Point(e.X, pStart.Y + ((int)(((panelHeight - 28) / (panelHeight * 1.0)) * (e.X - pStart.X))));
    4.             Rectangle rect = Rectangle.FromLTRB(pStart.X, pStart.Y, temp.X, temp.Y);
    5.             Bitmap bitmap = new Bitmap(panelWidth, panelHeight);
    6.  
    7.             Graphics g = Graphics.FromImage((Image) bitmap);
    8.  
    9.             g.DrawImage((Image) datasource, 0, 0); // FEHLER
    10.             g.DrawRectangle(new Pen(Brushes.Red, 3), rect);
    11.  
    12.             return bitmap;
    13.         }
    Ich habe bereits versucht das Objekt zu locken, aber vergeblich.

    Vielleicht könnt Ihr mir ja helfen.

    LG
    Leon
     
  2. sheel

    sheel I love Asm Administrator

    Hi

    welches Objekt und wo?

    Jedenfalls, diese ganzen GUI-Sachen (auch wenn sie auf Images verwendet werden) sind innen nicht threadsafe. Siehe die Invoke-Sache hier https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx (oder strukturier das Programm um, dass der Grafikteil nur in einem Thread passiert. Mit dem Invoke ist sonst nicht sicher, ob von der Verschnellerung durch Threads etwas übrig bleibt. Könnte sogar noch langsamer werden). Eine Fehermeldung ist noch nett (und nicht garantiert), schlimmer ist einfach komplettes Fehlverhalten.

    Und wenn man Thread.Abort braucht ist was falsch, und nicht nur an der "Schönheit" vom Code. Auch da: Wenn das in deinem Programm nötig ist, besser gleich umstrukturieren.
     
  3. Halfbax

    Halfbax Erfahrenes Mitglied

    Hallo sheel,

    Dritter Code-Teil Zeile 9 befindet sich der Thread übergreifende Fehler. Also muss das Bearbeiten des Bildes definitv im GUI Thread bleiben?

    LG
     
  4. Spyke

    Spyke Capoeirista Premium-User

    ich vermute mal datasource kommt ausm UI Thread (das bei RenderMouseEvent)
    und mehrere Threads versuchen auf das gleiche objekt zuzugreifen,
    eventuell mit lock etc. dies unter binden und/oder eine neue eigene Kopie des dataSoruce an den Thread weitergeben.

    und vorallem dein dataSource ist ein Image und er zeichnet sich immer selbst in ein neues Bitmap rein,
    wird zurückgegeben und ist das neue dataSource das sich selbst wieder in ein bitmap zeichnet ???
     
  5. Halfbax

    Halfbax Erfahrenes Mitglied

    RednerMouseEvent ist ein Methode aus der Klasse FractalHandler, diese Methode/Klasse wird im UI Thread gecalled. Dabei wird ein neuer Thread erstellt und die Daten als Delegate übergeben.

    FractalHandler bleibt im UI Thread bestehen.
     
  6. Spyke

    Spyke Capoeirista Premium-User

    delegates sind ja nixs andere wie zeiger auf die aufzurufenden Methoden,
    die referenz Objekte die übergeben werden bleiben ja die gleichen, eventuell diese locken das nicht mehrerer gleichzeitige Threads drauf zu greifen.
    wie gesagt dein datasource scheint mir nicht threadsafe, und hast ja da auch selber da FEHLER geschrieben