Cache Device Context

Asked by At

To draw some text I use

Size GetStringSize(LOGFONT logFont, string stringToMeasure)
{
     Font font = FontCache.Default.GetOrCreate(logFont);
     using(var graphics = System.Drawing.Graphics.FromHwnd(Display.HWND))
     {
        return TextRenderer.MeasureText(graphics, stringToMeasure, font, new Size(1000000, 1000000));
     }
}

I can cache the font object without issues. But I am not sure if I can cache the Graphics object, or if I can simply use the Graphics object of the current display by passing null to FromHWnd?

The performance issue is quite real:

Line #, Process, Stack Tag, Stack - (Callees of System.Drawing.ni.dll!System.Drawing.Graphics.FromHwnd(IntPtr)), Weight (in view) (ms)
7, ,   |  , System.Drawing.ni.dll!System.Drawing.Graphics.FromHwnd(IntPtr), 21,334.418715
8, ,   |  ,   |- System.Drawing.ni.dll!System.Drawing.Graphics.FromHwndInternal(IntPtr), 21,304.413686
9, ,   |  ,   |    |- System.Drawing.ni.dll!DomainBoundILStubClass.IL_STUB_PInvoke(System.Runtime.InteropServices.HandleRef, System.Drawing.FontStyle, Int32 ByRef), 21,264.422130
10, ,   |  ,   |    |    |- GdiPlus.dll!GdipCreateFromHWND, 21,244.429337
11, ,   |  ,   |    |    |    |- GdiPlus.dll!GpGraphics::GetFromHwnd, 21,214.423913
12, ,   |  ,   |    |    |    |    |- GdiPlus.dll!GpGraphics::GpGraphics, 20,824.349264
13, ,   |  ,   |    |    |    |    |    |- win32u.dll!ZwUserGetDC, 20,042.878233
14, ,   |  ,   |    |    |    |    |    |    |- ntoskrnl.exe!KiSystemServiceCopyEnd, 19,952.862751
15, ,   |  ,   |    |    |    |    |    |    |    win32kbase.sys!NtUserGetDC, 19,952.862751
16, ,   |  ,   |    |    |    |    |    |    |    |- win32kbase.sys!_GetDCEx, 19,842.849739
17, ,   |  ,   |    |    |    |    |    |    |    |    |- win32kbase.sys!HmgShareLock, 7,384.475206
18, ,   |  ,   |    |    |    |    |    |    |    |    |    |- win32kbase.sys!HANDLELOCK::vLockHandle, 3,085.609601
19, ,   |  ,   |    |    |    |    |    |    |    |    |    |    |- ntoskrnl.exe!ExAcquirePushLockExclusiveEx, 2,154.100038
20, ,   |  ,   |    |    |    |    |    |    |    |    |    |    |    |- ntoskrnl.exe!ExAcquirePushLockExclusiveEx<itself>, 1,984.037148

I spend 21s down there which is quite a lot. This is far away from ns. There are about 4 threads doing this concurrently to speed up drawing.

What can invalidate a cached Graphics object? In this case I do not draw anything only measure the text size so it should be pretty easy to cache. The font is specified with a negative Height which means it is declared in pixels.

0 Answers