Graphics.DrawImage blockiert UI-Thread

01/04/2011 - 15:00 von Armin Zingler | Report spam
Hi,

vorweg: FW 3.5, Win7-64, 3-Kern-CPU.

In meinem Programm habe ich mich gewundert, warum der UI-Thread so langsam
reagiert obwohl die Aufgabe, die ein zweiter Thread im Hintergrund ausführt,
den UI-Thread überhaupt nicht blockieren dürfte. Das zeigt sich an kaum
reagierenden Textboxen aber auch an ausbleibenden Tick-Ereignissen eines
UI-Timers. Folgender Code, "ready-to-use", zum Nachvollziehen in neuer Winforms-
Anwendung. Nach dem Start wird das Label hàufig aktualisert, nach dem
Anklicken des Buttons und Start des zweiten Threads aber nicht mehr.

Imports System.Threading

Public Class Form1

Private lbl As New Label With {.Parent = Me}
Private WithEvents button As New Button With {.Text = "start thread", .Top = 40, .Parent = Me}
Private WithEvents tmr As New System.Windows.Forms.Timer With {.Interval = 16, .Enabled = True}

Private Sub OnTimerTick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles tmr.Tick

lbl.Text = (Environment.TickCount / 1000).ToString("#,##0.000")
End Sub
Private Sub OnButtonClick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles button.Click

Dim t As New Thread(AddressOf Threadmain)
t.Name = "worker"
t.Priority = ThreadPriority.BelowNormal
t.Start()
button.Enabled = False
End Sub
Private Sub Threadmain()
Dim bmp1 As New Bitmap(2560, 1600)
Dim bmp2 As New Bitmap(2048, 1280)

Do
Using g = Graphics.FromImage(bmp2)
g.InterpolationMode = Drawing2D.InterpolationMode.Bicubic
g.DrawImage(bmp1, 0, 0, bmp2.Width, bmp2.Height)
End Using
Loop

End Sub

End Class


Warum ist das so? So wird der Multithreading-Ansatz ziemlich zunichte gemacht.
Wenn ich wàhrend dieser Gedenkpausen unterbreche, steht der UI-Thread irgendwo
im OnPaint des Labels beim GetDC. Das beisst sich wohl mit der Graphik-Operation
im zweiten Thread. Offenbar gibt es GDI(+) intern irgendwelche Locks. Worin
sind die begründet? Meine Threads teilen sich in meinem eigenen Code ja keine
gemeinsamen Ressourcen, aber GDI(+) intern scheint das anders zu sein. ^^

na klasse:

ntdll!NtWaitForSingleObject+0xa
ntdll!RtlpWaitOnCriticalSection+0xe8
ntdll!RtlEnterCriticalSection+0xd1
gdiplus!GpGraphics::GetHdc+0x23
gdiplus!GdipGetDC+0x9c

Soviel zum GetHdc. Und nun? Warum diese Warterei? Ich habe ja schon von
"ungünstigen" Locks in GDI+ gelesen, aber dabei ging es immer nur im
gemeinsam genutzte Ressourcen.


Armin
 

Lesen sie die antworten

#1 Thomas Scheidegger
02/04/2011 - 14:09 | Warnen spam
Hallo Armin

Ich habe ja schon von "ungünstigen" Locks in GDI+ gelesen



GDI+ ist voller konzeptioneller Altlasten & Probleme,
als Bsp uva ist es ja auch untauglich für den Server/Service-side Einsatz:
MS Blog (dort div Links, viele vorherige Posts)
http://weblogs.asp.net/bleroy/archi...d-ish.aspx

http://weblogs.asp.net/bleroy/archi...f-gdi.aspx

und wie man dort liest gilt dies leider zu einem kleinen Teil (insbeso unter
XP) sogar noch für WPF & WIC.

Generell, GDI+ ist gerade mal für simple, 'direkte'
Bildschirm/Window-Darstellung 'akzeptabel',
für wirkliche 'Imaging' - Anforderungen mit maximaler Performance wird ggf
eine separate (uU kommerz) Lib nötig (ggf [intern] gar native/mixed).
Insbesondere auch für hochauflösende Bitmaps (speicherintensiv).


Thomas Scheidegger - 'NETMaster'
http://dnetmaster.net/

Ähnliche fragen