我们在一个相当大而复杂的桌面应用程序中遇到了一些问题,其中使用Microsoft Ribbon for WPF(或与此相关的组合)会导致计算机挂起。
下面的简化代码似乎会触发许多计算机上的Windows挂起情况。有些计算机每次都会遇到这种情况,有些人永远不会体验到它。挂起将在某些计算机上使整个会话锁定(包括num lock和大写锁定),但在其他计算机上,鼠标仍会移动(num lock仍然停止运行)。当计算机无响应时,远程登录和网络共享似乎仍然有效,但无法结束控制台会话。
简而言之,似乎是行为的根本原因是几件事的结合:
我们稍后通过仅在几个选定的表单上使用WS_EX_COMPOSITED
来解决此问题,但我非常希望了解此问题的根本原因。
我还没有找到一种直接的方法来重现挂起,但是这个最小的应用程序似乎通过做一些最大化/恢复并将鼠标悬停在功能区上方来完成业务,至少在某些机器上完成按钮。
以下代码针对Microsoft WPF Ribbon .NET 4.0库编译为x86 .NET 4.0。
using System;
using System.Windows.Forms;
using Microsoft.Windows.Controls.Ribbon;
using System.Windows.Interop;
using System.Windows.Forms.Integration;
namespace WindowsRibbonHang
{
public class Form1 : Form
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
public Form1()
{
Ribbon ribbon = new Ribbon();
RibbonTab tab = new RibbonTab { Header = "FooTab" };
ribbon.Items.Add(tab);
RibbonSplitButton button = new RibbonSplitButton { Label = "FooButton" };
tab.Items.Add(button);
ElementHost elementHost = new ElementHost
{
Dock = DockStyle.Fill,
Child = ribbon,
};
Controls.Add(elementHost);
Dock = DockStyle.Fill;
ribbon.Loaded += (sender, args) => {
HwndSource hwndSource = System.Windows.PresentationSource.FromVisual(ribbon) as HwndSource;
HwndTarget hwndTarget = hwndSource.CompositionTarget;
hwndTarget.RenderMode = RenderMode.SoftwareOnly;
};
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
答案 0 :(得分:1)
尝试检查受影响计算机上的图形驱动程序是否是最新的。 WPF的工作方式与传统的GDI代码完全不同,因此有时不可靠的驱动程序会导致您描述的问题。
答案 1 :(得分:1)
正如您所发现的那样,问题来自复合Windows。我已经进一步分析了这个问题,它似乎与操作系统有关:
请参阅The Case of Slow WPF Rendering in a WinForms Application
两个线程尝试在循环中渲染和使对方窗口无效,其中在一个线程上复合Winforms窗口呈现,而在另一个线程上,WPF渲染线程执行相同的操作。只要软件渲染处于活动状态,就会在Win 7 - Win 10计算机上发生这种情况。
它看起来像一个DWM(桌面窗口管理器)问题,只有MS专家可以告诉我们WPF或WinForms是否违反了隐式合同,或者它是否是一个普通的DWM错误。