Что заставляет Windows зависать в этом приложении ленты WPF

У нас было несколько проблем с довольно большим и сложным настольным приложением, где использование Microsoft Ribbon для WPF (или связанное с этим сочетание) приводит к зависанию компьютера.

Приведенный ниже код, по-видимому, вызывает ситуацию зависания Windows на нескольких компьютерах. Некоторые компьютеры будут испытывать это зависание каждый раз, некоторые никогда не будут испытывать это. Зависание приведет к тому, что на некоторых компьютерах будет заблокирована вся сессия (включая num lock и caps lock), но на других мышь все равно будет двигаться (num lock все еще не работает). Когда компьютер перестает отвечать на запросы, кажется, что такие вещи, как удаленный вход в систему и общий доступ к сети, по-прежнему работают, но завершить сеанс консоли невозможно.

Короче говоря, основной причиной такого поведения является сочетание нескольких вещей:

Microsoft Ribbon для WPFПриложение Windows Forms, содержащее элемент управления WPF в ElementHostИспользование Windows Forms с двойной буферизацией (с помощью 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());
        }
    }
}

Ответы на вопрос(2)

Ваш ответ на вопрос