Multithreading SHGetFileInfo未将正确的句柄返回到图标
我正在使用SHGetFileInfo函数获取文件夹和不同文件类型的图标。根据这个函数的调用应该从后台线程完成,在调用组件之前,对象模型COM必须用CoInitialize或OleInitialize初始化。 我的代码如下所示:Multithreading SHGetFileInfo未将正确的句柄返回到图标,multithreading,winforms,winapi,Multithreading,Winforms,Winapi,我正在使用SHGetFileInfo函数获取文件夹和不同文件类型的图标。根据这个函数的调用应该从后台线程完成,在调用组件之前,对象模型COM必须用CoInitialize或OleInitialize初始化。 我的代码如下所示: public void SetHlinkImage(string path) { Shell32.OleInitialize(IntPtr.Zero); Task task = Task.Factory.StartNew((
public void SetHlinkImage(string path)
{
Shell32.OleInitialize(IntPtr.Zero);
Task task = Task.Factory.StartNew(() => { LoadIcons(path); });
}
private void LoadIcons(string path)
{
image = GetHlinkImage(path);
if (OwnerControl.InvokeRequired)
layout.ModuleControl.BeginInvoke((MethodInvoker)delegate ()
{
Shell32.OleUninitialize();
});
}
public Icon GetHlinkImage(string path)
{
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_ATTRIBUTES | Shell32.SHGFI_SMALLICON;
Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
IntPtr result = Shell32.SHGetFileInfo(path,
Shell32.FILE_ATTRIBUTE_DIRECTORY,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
Icon icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
WinApi.DestroyIcon(shfi.hIcon); // cleanup
return icon;
}
大多数情况下,问题出现在第一次调用代码之后,因此,当我尝试从图标句柄创建图标时,出现了一个异常:
System.ArgumentException:传递给图标的Win32句柄不正确
有效或类型错误
代码的进一步调用不会出现问题。
事实上,行为也在某种程度上取决于测试系统。在Windows10系统上很难重现此问题,但在Windows7上,这种情况经常发生
有人遇到过这个问题吗?来自Hans Passant的评论:
调用OleInitialize是没有意义的,CLR在启动线程之前已经初始化了COM。它失败了,因为你没有检查它的返回值,所以你看不到它。不知道这一点,它只是从那里螺旋上升到无法诊断的痛苦。是的,更多关于Win7的内容。您必须提供一个STA线程,如果需要在后台运行,那么考虑。不清楚,您是否在调用线程上正确初始化COM。@ IcTestTaby我正在初始化主线程中的COM。调用OLLIALIZITY是毫无意义的,CLR在启动线程之前已经初始化COM。它失败了,因为你没有检查它的返回值,所以你看不到它。不知道这一点,它只是从那里螺旋上升到无法诊断的痛苦。是的,更多关于Win7的内容。您必须提供一个STA线程,如果需要在后台运行,那么请考虑。每个使用COM的线程都必须初始化,并加入一个单元。@IInspectable这可能是过去,特别是将来出现许多其他问题的原因。我将努力缩小这一差距。非常感谢。