none
Von mehreren Threads auf das gleiche Objekt zugreifen.. RRS feed

  • Frage

  • Hallo Kollegen,

    Ich möchte aus einem Thread auf ein Writeablebitmap Objekt in einer Klasse im Hauptthread schreiben.

    Ohne Dispatcher.Begin Invoke funktiert es einmal gar nicht...

    Aber mein Problem ist es funktioniert nur wenn ich ein Thread.sleep(1); mache ansonsten tritt eine Out of Memory Exception auf..

    Leider werden 10000 * 10000 Werte in das Bitmap Objekt geschrieben und die Wartezeit summiert sich auf 100000000ms ~ 28h :(

    Wenn ich alle in Serie laufen lasse ohne Thread und Thread.sleep komme ich auf 2 Minuten

    Gibt es hier eine ander Möglichkeit Asynchron von mehrere Threads auf das Bitmap Objekt zu schreiben oder den Dispatcher vor Überlauf zu bewaren :(

    Vielen Dank für Input :)

    Code:

    private void OnMainWriteBitmap(object sender, WriteBitmapEventArgs e)
           {
                   Thread.Sleep(1);
     
                   this.Dispatcher.BeginInvoke((Action)(() =>
                   {                 
                       img.WritePixel(e.XCoordinate, e.YCoordinate, e.RectHigh, e.RectWidth, e.Pixels, e.Stride, e.Offset);
                   }             
               ));
    
           }


    Mittwoch, 29. März 2017 16:41

Antworten

  • Hallo,

    wenn mehrere Threads auf ein Objekt zugreifen wollen, dann müssen diese immer erst synchronisiert werden, was es sehr langsam werden lässt, wenn die eigentliche Berechnungslast nur sehr gering ist. Das merkst du ja selbst schon, durch die Ausdehnung der Zeit von 2 Minuten auf mehrere Stunden.

    Woher die OutOfMemoryException kommt kann ich dir nicht sagen.

    Wenn du ein Bild mit 10'000x10'000 Pixeln berechnen willst, dann kannst du dieses Bild auch aufteilen in mehrere in etwa gleichgroße Stücke. Bei einer 4-Kern CPU würden beispielsweise schon 4 Teile reichen. Um auf Nummer Sicher zu gehen kannst du auch 16 drauf machen. Du kannst dann also 16 Teilbilder generieren, wobei jedes 2500x2500 Pixel groß ist. Wenn dann alle fertig generiert wurden, kannst du sie schließlich zu einem großen Bild zusammen fügen. Auf diese weiße hast du nur am Ende den Synchronisationsaufwand und kannst trotzdem alle Kerne voll auslasten.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Mittwoch, 29. März 2017 18:31
    Moderator
  • Hallo,

    mit dem Ausschnitt kann man wenig anfangen. Da man außer einem WritePixel nichts weiter sieht, ist es schwer eine Lösung zu geben. Ein Sleep ist definitiv die schlechteste Lösung (nicht nur weil es länger dauert oder den Speicher "demoliert", es könnte immer auch schief gehen).

    Um mehrere Threads parallel eine Bitmap bearbeiten zu lassen, teilt man üblicherweise die Bitmap so weit wie möglich in Bereiche auf, die sich nicht überlappen. Damit vermeidet man unnötige Sperren. Auf diese Bereiche (Chunks) setzt man jeweils einen Thread an.

    Auch solltest Du überlegen, ob es wirklich notwendig ist, den GUI Thread vor dem Endergebnis (oder einem definitiven Zwischenstand) überhaupt anzusprechen.

    Gruß Elmar

    Mittwoch, 29. März 2017 18:40
    Beantworter

Alle Antworten

  • Hallo,

    wenn mehrere Threads auf ein Objekt zugreifen wollen, dann müssen diese immer erst synchronisiert werden, was es sehr langsam werden lässt, wenn die eigentliche Berechnungslast nur sehr gering ist. Das merkst du ja selbst schon, durch die Ausdehnung der Zeit von 2 Minuten auf mehrere Stunden.

    Woher die OutOfMemoryException kommt kann ich dir nicht sagen.

    Wenn du ein Bild mit 10'000x10'000 Pixeln berechnen willst, dann kannst du dieses Bild auch aufteilen in mehrere in etwa gleichgroße Stücke. Bei einer 4-Kern CPU würden beispielsweise schon 4 Teile reichen. Um auf Nummer Sicher zu gehen kannst du auch 16 drauf machen. Du kannst dann also 16 Teilbilder generieren, wobei jedes 2500x2500 Pixel groß ist. Wenn dann alle fertig generiert wurden, kannst du sie schließlich zu einem großen Bild zusammen fügen. Auf diese weiße hast du nur am Ende den Synchronisationsaufwand und kannst trotzdem alle Kerne voll auslasten.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Mittwoch, 29. März 2017 18:31
    Moderator
  • Hallo,

    mit dem Ausschnitt kann man wenig anfangen. Da man außer einem WritePixel nichts weiter sieht, ist es schwer eine Lösung zu geben. Ein Sleep ist definitiv die schlechteste Lösung (nicht nur weil es länger dauert oder den Speicher "demoliert", es könnte immer auch schief gehen).

    Um mehrere Threads parallel eine Bitmap bearbeiten zu lassen, teilt man üblicherweise die Bitmap so weit wie möglich in Bereiche auf, die sich nicht überlappen. Damit vermeidet man unnötige Sperren. Auf diese Bereiche (Chunks) setzt man jeweils einen Thread an.

    Auch solltest Du überlegen, ob es wirklich notwendig ist, den GUI Thread vor dem Endergebnis (oder einem definitiven Zwischenstand) überhaupt anzusprechen.

    Gruß Elmar

    Mittwoch, 29. März 2017 18:40
    Beantworter