none
请教VS2010 CMFCToolBar在低配置电脑运行时CPU飙升问题 RRS feed

  • 问题

  • CMFCToolBar::EnableTextLabels(TRUE)

    碰到一个巨坑,VS2010 MFC自带的TOOLBAR 图标+文本样式时,在低配置的电脑比如XP双核1G,先最小化再最大化切换时,MFC库中调用了DrawText导致瞬间高CPU,而且界面会短暂的黑屏,这个比较头疼,有没有什么办法解决?

    如果不使用此样式则CPU无明显变化5%以内波动可以接受,最关键是开启后CPU飙升、UI黑屏没办法接受.......

    windbg attach检测到是CMFCToolBarButton::OnCalculateSize这个函数里面DrawText导致的,有没有办法解决呢?

    0:005> !runaway
     User Mode Time
      Thread       Time
       0:c04       0 days 0:00:00.187
       5:9f8       0 days 0:00:00.000
       4:d8c       0 days 0:00:00.000
       3:830       0 days 0:00:00.000
       2:388       0 days 0:00:00.000
       1:420       0 days 0:00:00.000
    0:005> ~0 s
    eax=00ebb0c4 ebx=00000003 ecx=00eb15d8 edx=000003b8 esi=73ff0560 edi=73ff05c8
    eip=7c92e514 esp=0012eab0 ebp=0012ead8 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
    ntdll!KiFastSystemCallRet:
    7c92e514 c3              ret
    0:000> .clrstack
                   ^ Syntax error in '.clrstack'
    0:000> ~*kb
     
    .  0  Id: f40.c04 Suspend: 1 Teb: 7ffdd000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    0012eaac 77f0c4a7 77f1e8b7 08010a92 73ff04e8 ntdll!KiFastSystemCallRet
    0012ead8 73fd5300 08010a92 73ff04e8 00000003 GDI32!NtGdiGetTextExtentExW+0xc
    0012eb10 73fb2fdf 08010a92 73ff0374 73ff04e8 USP10!GDIPlace+0x40
    0012eb48 73fbad84 08010a92 73ff0374 73ff04e8 USP10!ScriptPlace+0xa7
    0012eba0 73fbb911 00000014 00000000 00000000 USP10!RenderItemNoFallback+0x27d
    0012ebcc 73fbb977 00000000 00000011 00000000 USP10!RenderItemWithFallback+0x22e
    0012ebf8 73fbc728 73ff0250 00000000 00000000 USP10!RenderItem+0x22
    0012ec28 73fb424e 00000000 08010a92 00000000 USP10!ScriptStringAnalyzeGlyphs+0x149
    0012ec40 62c248f8 08010a92 00eccca0 00000003 USP10!ScriptStringAnalyse+0x237
    0012ec8c 62c24651 08010a92 00eccca0 00000003 LPK!LpkStringAnalyse+0xfd
    0012ed8c 62c21269 08010a92 00000000 00000000 LPK!LpkCharsetDraw+0x2f3
    0012edc0 77d4e715 08010a92 00000000 00000000 LPK!LpkDrawTextEx+0x34
    0012ee00 77d1e113 08010a92 00000028 00000000 USER32!DT_DrawStr+0x54
    0012ee4c 77d1dbd1 08010a92 00eccca0 00eccca6 USER32!DT_GetLineBreak+0x77
    0012eef8 77d1da63 08010a92 ffffffff 00000003 USER32!DrawTextExWorker+0x23c
    0012ef1c 77d1fe40 08010a92 00eccca0 00000003 USER32!DrawTextExW+0x1e
    0012ef50 787b23cf 08010a92 00eccca0 00000003 USER32!DrawTextW+0x46
    0012ef6c 7874a2a8 00eccca0 00000003 0012efac mfc100u!CDC::DrawTextW+0x1a
    0012efcc 77d1b6d8 0012f058 7874448b 0012f02c mfc100u!CMFCToolBarButton::OnCalculateSize+0x16a
    0012f058 7874465c 00001ff4 00007fff 0012f0ac USER32!GetClientRect+0x1a
     
       1  Id: f40.420 Suspend: 1 Teb: 7ffdc000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    00e7fea4 7c92df4a 7c8096b0 00000002 00e7fed0 ntdll!KiFastSystemCallRet
    00e7fea8 7c8096b0 00000002 00e7fed0 00000001 ntdll!ZwWaitForMultipleObjects+0xc
    00e7ff44 77dc8631 00000002 00e7ff6c 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
    00e7ffb4 7c80b849 00000000 00000000 77dc8ae4 ADVAPI32!WmipEventPump+0x230
    00e7ffec 00000000 77dc848a 00000000 00000000 kernel32!BaseThreadStart+0x37
     
       2  Id: f40.388 Suspend: 1 Teb: 7ffdb000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    01f7fe14 7c92daaa 77e565e3 000006f8 01f7ff74 ntdll!KiFastSystemCallRet
    01f7fe18 77e565e3 000006f8 01f7ff74 00000000 ntdll!ZwReplyWaitReceivePortEx+0xc
    01f7ff80 77e56caf 01f7ffa8 77e56ad1 001872a8 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x12a
    01f7ff88 77e56ad1 001872a8 00166650 00000088 RPCRT4!RecvLotsaCallsWrapper+0xd
    01f7ffa8 77e56c97 0017b918 01f7ffec 7c80b849 RPCRT4!BaseCachedThreadRoutine+0x79
    01f7ffb4 7c80b849 00187528 00166650 00000088 RPCRT4!ThreadStartRoutine+0x1a
    01f7ffec 00000000 77e56c7d 00187528 00000000 kernel32!BaseThreadStart+0x37
     
       3  Id: f40.830 Suspend: 1 Teb: 7ffda000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    0207ff1c 7c92d21a 7c802512 00000000 0207ff50 ntdll!KiFastSystemCallRet
    0207ff20 7c802512 00000000 0207ff50 7c802670 ntdll!ZwDelayExecution+0xc
    0207ff78 7c802576 0000ea60 00000000 0207ffb4 kernel32!SleepEx+0x61
    0207ff88 769ad72e 0000ea60 00166920 769ad8b7 kernel32!Sleep+0xf
    0207ff94 769ad8b7 00000000 7c8865f8 00166920 ole32!CROIDTable::WorkerThreadLoop+0x14 [d:\nt\com\ole32\com\dcomrem\refcache.cxx @ 1358]
    0207ffa8 769ad91f 7c933e01 0207ffec 7c80b849 ole32!CRpcThread::WorkerLoop+0x1e [d:\nt\com\ole32\com\dcomrem\threads.cxx @ 185]
    0207ffb4 7c80b849 00166920 7c8865f8 7c933e01 ole32!CRpcThreadCache::RpcWorkerThreadEntry+0x1b [d:\nt\com\ole32\com\dcomrem\threads.cxx @ 54]
    0207ffec 00000000 769ad904 00166920 00000000 kernel32!BaseThreadStart+0x37
     
       4  Id: f40.d8c Suspend: 1 Teb: 7ffd9000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    021afe50 7c92df4a 7c8096b0 00000002 021afe7c ntdll!KiFastSystemCallRet
    021afe54 7c8096b0 00000002 021afe7c 00000001 ntdll!ZwWaitForMultipleObjects+0xc
    021afef0 77d19609 00000002 021aff18 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
    021aff4c 77d196b8 00000001 021affac ffffffff USER32!RealMsgWaitForMultipleObjectsEx+0x13e
    021aff68 4aea736a 00000001 021affac 00000000 USER32!MsgWaitForMultipleObjects+0x1f
    021affb4 7c80b849 00000000 00000000 00000011 gdiplus!BackgroundThreadProc+0x59
    021affec 00000000 4aea730e 00000000 00000000 kernel32!BaseThreadStart+0x37
     
    #  5  Id: f40.9f8 Suspend: 1 Teb: 7ffd8000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    02afffc8 7c97236a 00000005 00000004 00000001 ntdll!DbgBreakPoint
    02affff4 00000000 00000000 00000000 8e8e6542 ntdll!DbgUiRemoteBreakin+0x2d
    0:000> k
    ChildEBP RetAddr  
    0012eaac 77f0c4a7 ntdll!KiFastSystemCallRet
    0012ead8 73fd5300 GDI32!NtGdiGetTextExtentExW+0xc
    0012eb10 73fb2fdf USP10!GDIPlace+0x40
    0012eb48 73fbad84 USP10!ScriptPlace+0xa7
    0012eba0 73fbb911 USP10!RenderItemNoFallback+0x27d
    0012ebcc 73fbb977 USP10!RenderItemWithFallback+0x22e
    0012ebf8 73fbc728 USP10!RenderItem+0x22
    0012ec28 73fb424e USP10!ScriptStringAnalyzeGlyphs+0x149
    0012ec40 62c248f8 USP10!ScriptStringAnalyse+0x237
    0012ec8c 62c24651 LPK!LpkStringAnalyse+0xfd
    0012ed8c 62c21269 LPK!LpkCharsetDraw+0x2f3
    0012edc0 77d4e715 LPK!LpkDrawTextEx+0x34
    0012ee00 77d1e113 USER32!DT_DrawStr+0x54
    0012ee4c 77d1dbd1 USER32!DT_GetLineBreak+0x77
    0012eef8 77d1da63 USER32!DrawTextExWorker+0x23c
    0012ef1c 77d1fe40 USER32!DrawTextExW+0x1e
    0012ef50 787b23cf USER32!DrawTextW+0x46
    0012ef6c 7874a2a8 mfc100u!CDC::DrawTextW+0x1a
    0012efcc 77d1b6d8 mfc100u!CMFCToolBarButton::OnCalculateSize+0x16a
    0012f058 7874465c USER32!GetClientRect+0x1a
    0:000> g

    这个接口建议加上使用普通TextOut绘制方法,或者非多行文本则不需要DrawText来调用。

    如果重载继承的工具栏的话,貌似这个牵扯到的类比较多,不太好下手,HOOK的方式呢?


    • 已编辑 汪宁宇 2018年8月14日 7:38 ui
    2018年8月14日 7:34

全部回复

  • 你好,

    感谢在微软论坛发帖,

    >>碰到一个巨坑,VS2010 MFC自带的TOOLBAR 图标+文本样式时,在低配置的电脑比如XP双核1G,先最小化再最大化切换时,MFC库中调用了DrawText导致瞬间高CPU,而且界面会短暂的黑屏,这个比较头疼,有没有什么办法解决?

    如果不使用此样式则CPU无明显变化5%以内波动可以接受,最关键是开启后CPU飙升、UI黑屏没办法接受.......

    windbg attach检测到是CMFCToolBarButton::OnCalculateSize这个函数里面DrawText导致的,有没有办法解决呢?

    这里我建议你可以尝试使用Double buffering, 双缓冲技术的优点在于大部分绘制是离屏的。将离屏图像一次绘至屏幕上,比直接在屏幕上绘制要有效得多。

    这里有一个示例是关于double buffering的应用,你可以参照一下https://www.codeproject.com/tips/610388/flicker-free-text-scrolling-with-double-buffering

    Best Wishes,

    Jack Zhang


    MSDN Community Support<br/> Please remember to click &quot;Mark as Answer&quot; the responses that resolved your issue, and to click &quot;Unmark as Answer&quot; if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact <a href="mailto:MSDNFSF@microsoft.com">MSDNFSF@microsoft.com</a>.

    2018年8月15日 6:46
    版主
  • 这个是MFC类库,而且Toolbar、Button交叉引用,这种有办法继承重载再用双缓冲实现吗?
    2018年8月15日 7:53
  • 你好,

    应该可以,鉴于你目前的问题是出在CDC::DrawText这块, 你可以先将CDC这块设计成双缓存试试,具体实现网上有很多资料,你也可以先看看这个链接如何实现CDC双缓存的。
    https://www.codeproject.com/Articles/33/Flicker-Free-Drawing-In-MFC

    Best Wishes,

    Jack Zhang

    <o:p></o:p>


    MSDN Community Support<br/> Please remember to click &quot;Mark as Answer&quot; the responses that resolved your issue, and to click &quot;Unmark as Answer&quot; if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact <a href="mailto:MSDNFSF@microsoft.com">MSDNFSF@microsoft.com</a>.

    2018年8月16日 1:57
    版主