在进行托管到本机的互操作时,操作系统加载器锁定
OS Loader Lock when doing managed-to-native interop
我正在使用HwndHost将本机控件(c++)加载到WPF控件中。HwndHost定义如下:
class ControlHost : System.Windows.Interop.HwndHost
{
public IntPtr Handle;
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
// instantiate the native control
Handle = control.Handle;
return new HandleRef(this, control.Handle);
}
...
}
我的WPF项目有一个名为ControlHostElement的System.Windows.Controls.Border
。一般模式是获取ControlHostElement的句柄,实例化本机控件,并将其设置为WPF控件的子元素。这个模式是由MSDN规定的。我是用WPF页面上的一个按钮触发的:
private void btnHwndHost_OnClick(object sender, RoutedEventArgs e)
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}
问题是,当我实例化我的本机控件时,我在分配Child的行中得到OS Loader Lock错误:
DLL 'my.dll'试图在操作系统加载器锁定内托管执行。做不要尝试在DllMain或映像中运行托管代码初始化函数,因为这样做会导致应用程序挂起。
我不确定我是如何在加载器线程中,但我想我应该只是启动一个新线程来执行初始化和窗口句柄赋值:
private void btnHwndHost_OnClick(object sender, RoutedEventArgs e)
{
Thread loadControlHostThread = new Thread(
new ThreadStart(this.loadControlHostThread_DoWork));
loadControlHostThread.SetApartmentState(ApartmentState.STA);
loadControlHostThread.Start();
}
void loadControlHostThread_DoWork()
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}
不行:
类型为"System"的未处理异常。InvalidOperationException"发生在WindowsBase.dll
附加信息:调用线程无法访问此对象因为它属于另一个线程。
好了。也许我应该尝试让UI线程做这项工作:
void loadControlHostThread_DoWork()
{
this.Dispatcher.Invoke((Action)(() =>
{
myControlHost = new ControlHost();
ControlHostElement.Child = myControlHost;
}));
}
会导致相同的OS Loader Lock错误。初始化本机控件的正确方法是什么?
我得到一个OS Loader Lock错误
这不是错误,这是一个警告。来自MDA,托管调试器助手。它们是微软插入到CLR和调试器中的一小段代码,当看起来像您的程序正在做错误的事情时,它们会产生警告。这种类型不会产生异常,但会使程序挂起或以非常难以诊断的方式失败。
Loader锁当然符合这种模式,它是一个死锁隐藏在Windows内部。与加载程序相关联,这是操作系统中负责加载dll并调用它们的dlmain()入口点的部分。它使用一个内部锁来确保每次只调用一个DllMain()函数。它可以防止重入问题,这与Application.DoEvents()引起的麻烦非常相似。锁上的死锁很难调试,代码完全隐藏在操作系统和神秘的DllMain()函数中,您对此一无所知。真正的僵局很有可能会让你把你的头发撕成大块,除了没有MDA的秃斑之外,几乎没有什么可显示的。
不幸的是,MDA倾向于产生错误的警告。它并不总是意识到死锁实际上不可能发生。这是过于急切的,这是它必须像水晶球一样预测它可能发生的副作用。而不能将自己连接到操作系统内部,从而给您一个保证的警告。微软的Windows团队对托管代码一直不太满意,Longhorn在很长一段时间内都是一个痛处。加载器锁是。net 1.0中一个很大的很大的问题
在你的情况下,这几乎肯定是一个错误的警告,你可以完全确定CLR已经加载,否则你的程序不可能启动。
幸运的是,让它停止打扰你很简单:Debug + Exceptions,打开Managed Debugging Assistants节点,取消选中"LoaderLock"复选框。它很有可能会让您从此平静下来,让您专注于测试您的程序。
- std::原子加载和存储都需要吗
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 为什么加载SDF会导致Mobilizer创建闭环错误
- C++atioglxx.pdb未加载错误glBufferData OpenGL
- 如何使用tinyxml2从XML加载父实体和子实体
- 如何在C++中使用pybind11加载一个pickle python列表
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- Python ctypes:不会按预期加载 dll
- 为什么会出现 gettnig 运行时错误:加载类型为"_Bit_type"(stl_bvector.h) 的空指针?
- 我的程序有一个保存配置文件的GUI,如何双击此配置文件以直接加载带有配置数据的GUI?
- 保存/加载大量短数组到二进制文件
- 使用 SDL2 和SDL_image C++加载图像
- 无法使用加载库卸载注入的 dll (C++)
- 是否有原子加载非原子值的函数?
- 将 bmp 文件加载到 TSpeedButton 中
- 如何使用Qt 3D库加载和显示搅拌机.obj源文件场景
- 在进行托管到本机的互操作时,操作系统加载器锁定