.net 是什么导致Windows挂起在此WPF功能区应用程序中

.net 是什么导致Windows挂起在此WPF功能区应用程序中,.net,wpf,winforms,wpf-controls,ribbon,.net,Wpf,Winforms,Wpf Controls,Ribbon,我们在一个相当大且复杂的桌面应用程序中遇到了一些问题,其中使用Microsoft Ribbon for WPF(或与此相连接的各种东西的组合)会导致计算机挂起 下面的简化代码似乎触发了许多计算机上的Windows挂起情况。有些计算机每次都会经历这种挂起,有些则永远不会经历。在某些计算机上,挂起会使整个会话锁定(包括num-lock和caps-lock),但在其他计算机上,鼠标仍会移动(num-lock仍然无法工作)。当计算机没有响应时,远程登录和网络共享似乎仍然有效,但不可能结束控制台会话 简言

我们在一个相当大且复杂的桌面应用程序中遇到了一些问题,其中使用Microsoft Ribbon for WPF(或与此相连接的各种东西的组合)会导致计算机挂起

下面的简化代码似乎触发了许多计算机上的Windows挂起情况。有些计算机每次都会经历这种挂起,有些则永远不会经历。在某些计算机上,挂起会使整个会话锁定(包括num-lock和caps-lock),但在其他计算机上,鼠标仍会移动(num-lock仍然无法工作)。当计算机没有响应时,远程登录和网络共享似乎仍然有效,但不可能结束控制台会话

简言之,这种行为的根本原因似乎是以下几点的结合:

  • 用于WPF的Microsoft Ribbon
  • 在ElementHost中承载WPF控件的Windows窗体应用程序
  • 双缓冲Windows窗体的使用(通过使用CreateParams)
  • 在WPF功能区上使用软件渲染
我们后来通过仅在几个选定的表单上使用
WS_EX_COMPOSITED
解决了这个问题,但我非常想揭示这个问题的根本原因

我还没有找到一种直接的方法来重现挂起,但是这个最小的应用程序似乎通过执行一些最大化/恢复并将鼠标悬停在功能区按钮上方来完成业务,至少在某些机器上是这样

下面的代码编译为x86.NET4.0,与.NET4.0库相对

使用系统;
使用System.Windows.Forms;
使用Microsoft.Windows.Controls.Ribbon;
使用System.Windows.Interop;
使用System.Windows.Forms.Integration;
命名空间窗口RibbonHang
{
公开课表格1:表格
{
受保护的重写CreateParams CreateParams
{
得到
{
CreateParams cp=base.CreateParams;
cp.ExStyle |=0x020000000;//启用WS_EX_COMPOSITED
返回cp;
}
}
公共表格1()
{
Ribbon Ribbon=新功能区();
RibbonTab选项卡=新RibbonTab{Header=“FooTab”};
ribbon.Items.Add(选项卡);
RibbonSplitButton按钮=新RibbonSplitButton{Label=“FooButton”};
选项卡.项目.添加(按钮);
ElementHost ElementHost=新ElementHost
{
Dock=DockStyle.Fill,
孩子=丝带,
};
控件。添加(elementHost);
Dock=DockStyle.Fill;
ribbon.Loaded+=(发送方,参数)=>{
HwndSource HwndSource=System.Windows.PresentationSource.FromVisual(功能区)作为HwndSource;
HwndTarget HwndTarget=hwndSource.CompositionTarget;
hwndTarget.RenderMode=仅限RenderMode.SoftwareOnly;
};
}
}
静态类程序
{
/// 
///应用程序的主要入口点。
/// 
[状态线程]
静态void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(新Form1());
}
}
}

尝试检查受影响计算机上的图形驱动程序是否是最新的。WPF的工作原理与传统的GDI代码非常不同,因此有时不可靠的驱动程序可能会导致您描述的那种问题。

正如您所发现的,这个问题来自复合窗口。我进一步分析了这个问题,它似乎是一个与操作系统相关的问题:

两个线程尝试在循环中渲染并使彼此窗口无效,其中一个线程上的复合Winforms窗口渲染,另一个线程上的WPF渲染线程执行相同的操作。只要软件渲染处于活动状态,Win7-Win10机器上就会发生这种情况


这看起来像是一个DWM(桌面窗口管理器)问题,只有MS专家才能告诉我们WPF或WinForms是否违反了隐式契约,或者它是否是一个普通的DWM错误

我还认为它可能与图形驱动程序有关。有趣的是,这似乎发生在多个图形卡供应商之间。正如你所建议的,我也尝试过更新到最新的图形驱动程序。你解决过这个问题吗?在这个问题上,我只能找到这个问题和另一个问题,但都没有找到解决办法。@EduardoWada不太可能。正如@Olly所说,这可能与WPF与图形驱动程序交互的方式有关。“解决方案”是禁用
CreateParams
覆盖,并在目标更明确的表单上执行该操作。