你如何解决WPF UI问题?

11

我正在开发一款WPF应用程序,有时会出现奇怪问题并在UI中出现“卡顿”。它不稳定,会在不同的页面上发生,但它经常发生,这是一个大问题。需要指出的是,它并不像下面描述的那样真正的“卡死”。

我的第一个想法是某些按钮的动画可能是问题所在,因为它们在大多数页面上都被使用了。但即使我删除它们,卡顿仍然会发生,尽管似乎少了一点。当卡顿发生时,我尝试打断点调试,但从未看到任何代码。我的代码没有运行。我还注意到,“卡顿”不是完全的。我有让表单拖动的代码(它没有边框或标题),它仍在工作。我还有自己的关闭按钮,当我点击它时可以关闭程序。点击按钮似乎实际上是有效的,因为我的代码运行了,但UI永远不会更新以显示新页面。

我正在寻找任何建议、工具或技术来解决这个奇怪的问题,如果你有任何想法,我将非常感激。

编辑:刚刚又出现了这种情况,所以这次当我尝试打断点时,我选择了“显示反汇编代码”。它带我到了“MS.Win32.UnsafeNativeMethods.GetMessageW”。栈跟踪如下:

[Managed to Native Transition]  
WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + 0x15 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x48 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) + 0x8b bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x1e bytes PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes PresentationFramework.dll!System.Windows.Application.Run() + 0x19 bytes WinterGreen.exe!WinterGreen.App.Main() + 0x5e bytes C# [Native to Managed Transition] [Managed to Native Transition] mscorlib.dll!System.AppDomain.nExecuteAssembly(System.Reflection.Assembly assembly, string[] args) + 0x19 bytes mscorlib.dll!System.Runtime.Hosting.ManifestRunner.Run(bool checkAptModel) + 0x6e bytes mscorlib.dll!System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() + 0x84 bytes mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext, string[] activationCustomData) + 0x65 bytes mscorlib.dll!System.Runtime.Hosting.ApplicationActivator.CreateInstance(System.ActivationContext activationContext) + 0xa bytes mscorlib.dll!System.Activator.CreateInstance(System.ActivationContext activationContext) + 0x3e bytes Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() + 0x23 bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes
5个回答

6

尝试移除窗口的无边框行为,看看是否有所帮助。此外,您是否在使用BeginInvoke()或Invoke()调用任何长时间运行的操作?

另一件需要注意的事情是:当您打断点停留在代码中时,尝试查看除主线程以外的其他线程。其中一个可能会阻塞UI线程。


有时会执行一些异步进程;然而这种行为可能发生在任何时候,包括刚启动时几乎没有运行任何东西的情况下。我将尝试移除无边框行为。 - palehorse
给未来阅读此内容的其他人一个提示:永远不要在你的Dispatcher上调用Invoke()或BeginInvoke()长时间运行的操作。你的UI将会出现卡顿...使用线程、BackgroundWorker或类似的东西。 - Bob King
Bob是正确的,如果你在UI线程上一次做太多的事情,UI将变得无响应。你希望在UI线程上尽可能少地执行任何操作;任何大型操作都应该在后台线程上完成。 - Rob

6

如果你的WPF应用程序出现性能问题,可能会导致程序挂起。尝试使用Perforator工具,查看是否有部分内容采用软件渲染方式或者你的应用程序使用了过多的视频内存。


我之前不知道那个工具。我很快会安装它。 - palehorse

4

一款非常好用的工具是Snoop。它非常适合查看在给定时间WPF对象在可视树上所显示的内容。我不确定它能帮多少忙,但有可能您的UI线程被大量无关的任务所卡住了。使用Snoop可能会帮助您追踪屏幕上的内容,从而给您一个查找问题的思路。


1
Snoop 可能无法帮助,因为代码已经挂起,但问题提问者无法进入该挂起状态。 - Bob King
我已经尝试了Snoop,但正如Bob所指出的,它没有帮助。我注意到了另一件事情,我将编辑原始问题以包括它。 - palehorse

4

如Bob King建议的那样,我已经取消了无边框行为。到目前为止,这似乎已经解决了问题。

现在的问题是,我该如何修复这个问题?该产品设计为没有边框,有一些圆角和透明部分。


我也需要这个。我刚刚碰到了完全相同的问题。我注意到当我切换到窗口应用程序时,性能大幅提升。 - EightyOne Unite

1

太好了...看起来这个问题与无边界窗口无关(至少在我这里不是)。

当你将 AllowsTransparency 设置为 true 时,会有很大的性能损失。它似乎会导致整个应用程序挂起 UI 线程。非常奇怪的行为。可能与 this ticket 有关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接