【问题标题】:What causes Windows to hang in this WPF Ribbon application是什么导致 Windows 在此 WPF 功能区应用程序中挂起
【发布时间】:2013-07-04 15:26:38
【问题描述】:

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

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

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

  • 用于 WPF 的 Microsoft 功能区
  • 在 ElementHost 中托管 WPF 控件的 Windows 窗体应用程序
  • 使用双缓冲 Windows 窗体(通过使用 CreateParams)
  • 在 WPF 功能区上使用软件呈现

我们后来通过仅在少数选定的表单上使用WS_EX_COMPOSITED 解决了这个问题,但我非常想找出这个问题的根本原因。

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

以下代码编译为 x86 .NET 4.0,针对 Microsoft WPF Ribbon .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());
        }
    }
}

【问题讨论】:

  • 你解决过这个问题吗?我只能在这个问题上找到这个问题和另一个stackoverflow.com/questions/7719627/…,但都没有找到解决方案。
  • @EduardoWada 不是。正如@Olly 所说,这可能与 WPF 与图形驱动程序交互的方式有关。 “解决方案”是禁用 CreateParams 覆盖,而是在更有针对性的表单上执行此操作。

标签: .net wpf winforms wpf-controls ribbon


【解决方案1】:

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

【讨论】:

  • 我也认为它可能与图形驱动程序有关。值得注意的是,这似乎发生在多家显卡供应商身上。我也按照您的建议尝试更新到最新的图形驱动程序。
【解决方案2】:

正如您所发现的那样,复合 Windows 出现了问题。我已经进一步分析了这个问题,它似乎是一个与操作系统相关的问题:

The Case of Slow WPF Rendering in a WinForms Application

两个线程尝试在一个循环中呈现和使其他窗口无效,在一个线程上复合 Winforms 窗口呈现,而在另一个线程上 WPF 呈现线程执行相同的操作。只要软件渲染处于活动状态,这就会在 Win 7 - Win 10 机器上发生。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多