- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们有一个庞大的代码库,用于使用 Qt 在 C++ 中处理和可视化图像。现在用户想要在此基础上进行构建,但他们的代码库是带有 WPF 的 .NET Core 3.1。我们使用 PInvoke 来接口(interface)原生代码,并且可以非常成功地加入项目。少数原生小部件嵌入了 Win32-in-WPF-HwndHost wrapper 。一切都很好,我们对我们获得的里程感到非常高兴!
只有一个阻塞问题:HwndHost
方法BuildWindowCore
有时会陷入僵局。我们可以确定死锁的根本原因:
当BuildWindowCore
调用 Qt 将 native 小部件重新设置为托管小部件的句柄,我们使用阻塞调用来确保重新设置完成。然而,在重新设置小部件的父级期间,Qt 有时会调用 DefWindowProc
将未处理的窗口消息传递回父 WPF 小部件。由于 WPF 线程被调用 Qt 阻塞,这是一个循环阻塞等待,以死锁结束。
虽然我可以理解这个问题,但我们对 WPF GUI 线程的了解还不够,无法解决这个问题。
到目前为止,我们尝试了什么:
await
)但 BuildWindowCore
不能是异步方法。 BuildWindowCore
, 并称之为 async
稍后,但 HwndHost
小部件需要在 BuildWindowCore
中进行重新设置,或者我们得到一个 WPF 错误,即 native 小部件句柄不是(还)WPF 小部件的子小部件。 await Dispatcher.Yield(DispatcherPriority.ApplicationIdle)
,但这是在
async
方法。
protected override HandleRef BuildWindowCore(HandleRef HWNDParent)
{
NativeCode.beginReParenting(HWNDParent.Handle);
while (!NativeCode.reParentingCompleted()) {
// This method is async, is it clean to call it like this?
Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
}
return new HandleRef(this, NativeCode.getEmbeddedWidgetHandle());
}
我的问题:
async Dispatcher.Yield()
GUI 线程中的方法,当 BuildWindowCore
本身不能异步吗? HwndHost.BuildWindowCore()
时不阻塞 WPF GUI 线程? ? 最佳答案
您的 WPF 泵(调度程序)被阻塞。 Async/await/Yield 对您没有帮助,因为您不在异步功能中。
当 WPF 位于 BuildWindowCore() 中时,您需要 WPF 保持抽水。您可以通过在不同的线程上调用您的 native 代码来做到这一点,然后让您的 WPF 线程坐下来并泵送消息,直到工作线程完成。您可以使用 Dispatcher.PushFrame .
希望是这样的:
protected override HandleRef BuildWindowCore(HandleRef HWNDParent)
{
// call into QT in worker thread
var reParentTask = Task.Run(() => NativeCode.beginReParenting(HWNDParent.Handle));
// pump messages while we wait for QT to do its stuff
var frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(delegate (object f)
{
((DispatcherFrame)f).Continue = !reParentTask.IsCompleted;
return null;
}),frame);
Dispatcher.PushFrame(frame);
return new HandleRef(this, NativeCode.getEmbeddedWidgetHandle());
}
关于c# - WPF : How to not block the GUI thread in HwndHost. BuildWindowCore 中的死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63988620/
我正在尝试在我的进程中托管另一个进程的窗口。为此,我使用 HwndHost,如下所示: public class MyHandle : HwndHost { #region User32.dl
我们有一个庞大的代码库,用于使用 Qt 在 C++ 中处理和可视化图像。现在用户想要在此基础上进行构建,但他们的代码库是带有 WPF 的 .NET Core 3.1。我们使用 PInvoke 来接口(
我是一名优秀的程序员,十分优秀!