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
Hallo,
guckst du: [FAQ] Warum blockiert mein GUI?
**:::
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?
Hallo,
bei deinem Code fehlt irgendwie die Verwendung der Bitmaps. Was machst du mit denen denn?
Baka wa shinanakya naoranai.
Mein XING Profil.
Servus!
Schau mal hier nach:
[Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox)
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....
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
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.
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
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
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.
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
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.
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
Siehe auch Öffnen & Vorverarbeiten eines Bildes in einen extra Thread packen, um das GUI nicht zu blockieren? ff.