We've had a few problems with a rather large and complex desktop application where the use of Microsoft Ribbon for WPF (or a combination of things connected to this) causes the computer to hang.
The boiled down code below seems to trigger a Windows hang situation on a number of computers. Some computers will experience this hang every time, some will never experience it. The hang will, on some computer make the entire session lock up (including num lock and caps lock), but on others, the mouse will still move (num lock still out of business). When the computer becomes unresponsive, it seems things like remote logon and network sharing still works, but it is not possible to end the console session.
In short, what seems to be the root cause of the behavior is the combination of a few things:
- Microsoft Ribbon for WPF
- Windows Forms application hosting the WPF control in an ElementHost
- The use of double buffered Windows Forms (by use of CreateParams)
- The use of software rendering on the WPF ribbon
We have later solved this issue by using WS_EX_COMPOSITED
only on a few selected forms, but I'd very much like to uncover the root cause of this issue.
I've yet to discover a straight forward way to reproduce the hang, but this minimal application seems to get the business done, at least on some machines, by doing a bit of maximize/restore and hovering the mouse above the ribbon button.
The following code is compiled as x86 .NET 4.0, against the Microsoft WPF Ribbon .NET 4.0 library.
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());
}
}
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…