我面临一个问题,即WPF应用程序无法更新进度条,即使wpf窗口上的按钮停止发光,直到我移动窗口,然后一切都很好。
每次我更新实际生成WM_PAINT消息但没有解决问题的进度条时,我都尝试调用InvalidateRect。这个问题是随机发生的,有些时候不会发生。
我的应用程序在后台使用DirectShow,增强视频渲染用于视频渲染。如果我用VMR替换增强型视频渲染器,一切正常。
如果有人能帮助我,我将不胜感激。
由于 苏赫拉布。
答案 0 :(得分:7)
我理解为什么你尝试使用WM_PAINT解决问题。但是,WM_PAINT实际上与WPF渲染无关。
基本上,这是WPF在屏幕上首次显示Window(或HwndSource,ElementHost,...)时的渲染方式:
从那时起,每当进行影响显示的属性更改时,步骤4-7的相关部分将以极其有效的增量方式重复,仅更新需要更新的内容。
这里需要注意的关键是,只要有渲染工作要完成,就会安排Dispatcher回调。这意味着您的UI将继续呈现:
此外,输入事件的处理发生在输入优先级,因此如果您希望鼠标悬停在按钮上,则至少需要让Dispatcher执行输入优先级。
由于WPF的工作方式,发送WM_PAINT根本不做任何事情。你想要做的是让Dispatcher有机会处理它的队列。通常,这是通过从UI线程调用Dispatcher.Invoke并传递低于要刷新的事件的优先级来完成的,例如:
Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(() => {}));
请注意,该操作根本不起作用。但是,在执行空操作之前,对Dispatcher.Invoke的调用无法返回,并且在执行所有优先级较高的操作之前,空操作无法执行。因此,上面的代码具有强制渲染同步发生的效果,类似于在Win32中执行SendMessage(WM_PAINT,...)时会发生的情况。
诊断问题的一种方法是设置DispatcherTimer以定期写入控制台。通过以各种优先级运行此计时器,您可以确定阻塞Dispatcher队列的内容。如果没有任何级别正在运行,则可能是外部锁定UI线程的东西,在这种情况下,破坏进程并检查堆栈可能会有所帮助。分析工具对此更好。在每种情况下,确定进程是执行代码还是等待锁定。如果它正在执行代码,请弄清楚为什么该代码永远不会返回以给Dispatcher一个运行的机会。如果它正在等待锁定,请确定谁持有该锁定。