Laden...

[erledigt] DrawImage blockiert GUI Thread

Erstellt von harrylask vor 14 Jahren Letzter Beitrag vor 14 Jahren 4.834 Views
H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren
[erledigt] DrawImage blockiert GUI Thread

Hallo Leute,
ich erstelle in einer asynchronen Methode die zyklisch aufgerufen wird ein Bitmap welches ich am Ende je nach Fenstergrösse skaliere, funktioniert prinzipiell einwandfrei. Der Haken ist das mir die Anweisung Graphics.DrawImage() für einen Bruchteil den GUI Thread blockiert.


    private void timer1_Tick(object sender, EventArgs e)
    {
      new MethodInvoker(this.Test).BeginInvoke(null, null);
    }

    private void Test()
    {
      Bitmap Source = new Bitmap(4380, 1650);
      Bitmap Destination = new Bitmap((int)(Source.Width * 0.26F), (int)(Source.Height * 0.26F));

      using (Graphics g1 = Graphics.FromImage(Source))
      {
        g1.Clear(Color.White);

        using (Graphics g2 = Graphics.FromImage(Destination))
        {
          g2.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
          g2.DrawImage(Source, 0, 0, Destination.Width, Destination.Height);
        }
      }
    }

Wenn ich die g.DrawImage() Anweisung weglasse gehts, hat jemand eine Idee warum das so ist bzw. wie ich das umgehen kann?

Danke, harrylask

1.696 Beiträge seit 2006
vor 14 Jahren

Ich bin verantwortlich für das, was ich sage, nicht für das, was du verstehst.

**:::

H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren

Der Link hilft mir nicht weiter, ich lagere ja die Erstellung des Bitmaps in einen extra Thread aus damit mir der GUI Thread während dessen nicht blockiert wird. Er wird aber trotzdem kurz blockiert (beim Resizen, bewegen eines anderen Fensters auf der Oberfläche des GUIs). Die Ursache ist Graphics.DrawImage() die eigentlich eh im Nebenthread ausgeführt wird, warum stockt mir dann die Hauptanwendung?

6.862 Beiträge seit 2003
vor 14 Jahren

Hallo,

bei deinem Code fehlt irgendwie die Verwendung der Bitmaps. Was machst du mit denen denn?

Baka wa shinanakya naoranai.

Mein XING Profil.

C
11 Beiträge seit 2009
vor 14 Jahren
Gelöschter Account
vor 14 Jahren

Er wird aber trotzdem kurz blockiert (beim Resizen, bewegen eines anderen Fensters auf der Oberfläche des GUIs). Die Ursache ist Graphics.DrawImage() die eigentlich eh im Nebenthread ausgeführt wird, warum stockt mir dann die Hauptanwendung?

wenn es im nebenthread läuft kann die methode nciht die ursache sein... du suchst den fehler an der falschen stelle....

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo harrylask,

die Frage von talla finde ich auch interessant.

Wenn es wirklich keine andere langlaufende Operation im GUI-Thread gibt, dann halte ich es für möglich, dass der Worker-Thread einfach so rechenintensiv ist, dass er dem GUI-Thread so viel Rechenzeit entzieht, dass dieser kurz "blockiert".

herbivore

Gelöschter Account
vor 14 Jahren

aber dann würden auch alle anderen anwendungen diesen hänger haben

5.299 Beiträge seit 2008
vor 14 Jahren

Ich hab beim Threading mit Delegate.Begininvoke() auch den eindruck, dass der Threadpool träge reagiert.
Also die ersten paar male merkich eine zeitl Verzögerung, bis ein Thread rausgerückt wird, später dann nicht mehr.

Wäre eh eine Überlegung, einen NebenThread im Dauerbetrieb laufen zu lassen, oder auch gleich einen System.Timers.Timer, oder einen System.Threading.Timer zu nehmen, die ticken ja nebenläufig.

Der frühe Apfel fängt den Wurm.

H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren

So, vorerst danke für die Hinweise.

@talla herbivore
Die Anwendung ist für einen Leitstand einer Anlage auf deren Oberfläche die Anlage selbst animiert dargestellt wird. Die Teile der Anlage liegen als Bitmaps als Resource in der Anwendung vor. In bestimmten Intervallen wird asynchron eine Methode aufgerufen die das Bitmap erstellt und je nach Auflösung skaliert.

@Allgemein
Wenn ich so wie ErfinderDesRades vorschlägt einen DauerbetriebNebenThread laufen lasse ohne der Anweisung Graphics.DrawImage() reagiert meine Hauptanwendung wie gewünscht. Füge ich aber Graphics.Draw() ein reagiert die Anwendung träge wenn sie mE irgendwas mit GDI zu tun bekommt.

aber dann würden auch alle anderen anwendungen diesen hänger haben

Nö, ist nicht der Fall. Alle anderen funktionieren normal.

Mein Verdacht ist das es irgendwie mit der GDI zu tun hat, hab aber keine Ahnung warum, mir fällt dazu auch keine Lösung ein wie ich das abstellen könnte. Könnt ihr das Verhalten eigentlich reproduzieren?

So long, harrylask

H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren

Meine Lösung ist die das mir eine externe Anwendung mit der ich über einen IpcChannel kommuniziere das Bitmap erstellt, sämtliche Versuche die im Kontext meiner Anwendung liefen brachten den GUI Thread ins stocken.

Grüsse, harrylask

5.299 Beiträge seit 2008
vor 14 Jahren

ipcChannel, das heißt, hinter der property "Source" steckt ein Proxy, der erstmal über den Channel die bitmap anfordern muß?

nee, ist quatsch.

aber wennich den code jetzt angucke, wunder ich mich, dass du 2 Graphics-objekte brauchst. mit g1 löschst du die Source, mit g2 kopierst du die (gelöschte) Source nach Destination.

komisch.

Der frühe Apfel fängt den Wurm.

H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren

Hallo ErfinderDesRades,

aber wennich den code jetzt angucke, wunder ich mich, dass du 2 Graphics-objekte brauchst. mit g1 löschst du die Source, mit g2 kopierst du die (gelöschte) Source nach Destination.

Das Beispiel dient nur zum Zweck, es ist kein Originalcode. Ohne Graphics.DrawImage() ist bei mir kein Ruckeln feststellbar, mit schon.

ipcChannel, das heißt, hinter der property "Source" steckt ein Proxy, der erstmal über den Channel die bitmap anfordern muß?

nee, ist quatsch.

Jepp, wie würde dein Ansatz aussehen?

Grüsse, harrylask

5.299 Beiträge seit 2008
vor 14 Jahren

ich nehme mal an, jepp heißt in diesem zusammenhang, dass tatsächlich ein proxy die bitmap ranschaffen muß.

Das holen sollte dann wohl im nebenthread geschehen, nicht im gui-thread.

und das sollte man wohl cachen, dass die nur einmal geholt wird, nicht bei jeder verwendung neu.

Der frühe Apfel fängt den Wurm.

H
harrylask Themenstarter:in
59 Beiträge seit 2005
vor 14 Jahren

Hallo ErfinderDesRades,
ja, die "Serialisierung", Erstellung und "Deserialisierung" wird in einem Nebenthread gemacht, die Erstellung selbst in einer externen Applikation. Schön ist wieder was anderes aber somit bekomme ich wenigstens das lästige ruckeln weg.

Wie gesagt, sämtliche Ansätze (Threads und deren Prioritäten, AppDomains oder eine zweite MessageLoop (was ich mir von dem versprach weiss ich nicht mehr)) verliefen bei mir im Sande, das ruckeln blieb. Alles was irgendwie im Kontext meiner Anwendung lief half nicht.

Grüsse, harrylask