【发布时间】:2018-08-27 23:39:33
【问题描述】:
我有一个 C++ MFC SDI 应用程序 (MGen),它显示在 Windows 10 上启动和显示 GUI 之间有 10-20 秒的暂停。我使用 MSVS2017 性能分析器(CPU 使用)来查找在发布中占用 CPU 时间的函数建造。此暂停在ProcessShellCommand 运行中,特别是在CMFCRibbonBar::RecalcLayout、CMFCRibbonBar::LoadFromResource、CDockingManager::EnableAutoHidePanes 中。
当某些程序关闭时,暂停似乎会被删除或减少。首先,我注意到关闭 Windows 任务管理器修复了暂停并再次启动它会返回暂停。然后我发现即使没有任务管理器也会发生暂停。关闭 Chrome 有助于将暂停时间减少到 2-3 秒。
我也发现空项目如果是MSVS2017中的MFC向导创建的也存在这个问题。
我试过了:
- 重建解决方案 - 没有帮助
- 所有发布和调试版本(x86 和 x64)都有这个问题
- 在 MSVS 之外运行,在不同的 PC 上运行(Windows 10 也是)- 没有帮助
- 重新启动 Windows 似乎可以暂时解决此问题(暂停消失)。
- 我在 CMainFrame::OnCreate() 中注释掉了 OnApplicationLook() 调用。暂停仍然存在,因为这些函数现在是从其他地方调用的:Image1Image2
代码可以在GitHub找到:
BOOL CMGenApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
EnableTaskbarInteraction(FALSE);
// Initialize GDI+
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
SetRegistryKey(_T("MGen"));
LoadStdProfileSettings(10); // Load standard INI file options (including MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMGenDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMGenView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
// Enable DDE Execute open
EnableShellOpen();
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
return TRUE;
}
附:我在两台 PC 中都使用了最新的组件(Intel I7-8700K 配备 64Gb RAM 和 Intel I7-4770K 配备 32Gb RAM、SSD)并且没有遇到性能问题。在应用程序启动暂停期间,CPU 仅由应用程序使用。
详细的性能分析器结果:
更详细的分析:
ExitInstance 也有同样的问题:
【问题讨论】:
-
嗯,那些需要这么长时间的函数里面有什么?他们是否可能从远程位置获取图像?进行繁重的计算?由于重新启动似乎暂时有帮助,是否还涉及其他应用程序?你能通过反复做这件事来恶化问题吗?
-
感谢您的回复!我将尝试获取那些 MFC 源并检查那里发生了什么。它们是标准的,我没有覆盖它们。这对我来说似乎很奇怪,因为从 ProcessShellCommand 开始没有我的代码。
-
请看,我添加了两个屏幕截图,显示了这些函数内部发生的情况。他们不获取远程图像(仅限本地)。据我所知,没有涉及其他应用程序。不确定我是否可以重复这样做,因为这是 MFC 框架的一部分。
-
在 mainframe.cpp 中禁用临时 OnApplicationLook(..) 并检查此问题是否仍然存在。您可以稍后通过单击 View-Application Look 在程序中手动调用它。
-
找到了一些关于它的信息:developercommunity.visualstudio.com/content/problem/136952/… 我还收集了其他信息并与这里的经典菜单进行了比较:github.com/rualark/MGen/issues/1990
标签: c++ windows visual-studio mfc freeze