C# 方法在3310次成功后失败

C# 方法在3310次成功后失败,c#,icons,pinvoke,handle,C#,Icons,Pinvoke,Handle,我继承了以下扩展方法,该方法基于文件路径创建ImageSource对象 public static class ImageSourceExtensions { [StructLayout(LayoutKind.Sequential)] public struct SHFILEINFO { public IntPtr hIcon; public int iIcon; public uint dwAttributes;

我继承了以下扩展方法,该方法基于文件路径创建ImageSource对象

public static class ImageSourceExtensions
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SHFILEINFO
    {
        public IntPtr hIcon;
        public int iIcon;
        public uint dwAttributes;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string szDisplayName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
        public string szTypeName;
    };

    public const uint SHGFI_ICON = 0x100;
    public const uint SHGFI_LARGEICON = 0x0;

    [DllImport("shell32.dll")]
    public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

    public static ImageSource GetIconFromFolder(this string filePath)
    {
        SHFILEINFO shinfo = new SHFILEINFO();
        SHGetFileInfo(filePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo),
                SHGFI_ICON | SHGFI_LARGEICON);

        using (Icon i = Icon.FromHandle(shinfo.hIcon))
        {
            //Convert icon to a Bitmap source
            ImageSource img = Imaging.CreateBitmapSourceFromHIcon(
                                    i.Handle,
                                    new Int32Rect(0, 0, i.Width, i.Height),
                                    BitmapSizeOptions.FromEmptyOptions());

            return img;
        }
    }
}
此扩展方法对文件夹和文件都非常有效3310次。在第3311次方法调用上,引发以下异常:

'传递给图标的Win32句柄无效或错误 类型'

使用shinfo.hIcon属性时引发此错误

这个错误最初是在我的主应用程序中抛出的,每次都在不同的文件中。此后,我将该类提取到一个新项目中,通过单击按钮可以抛出相同的错误(相同次数后):

String path = @"C:\Generic Folder\Generic Document.pdf";

        for (int i = 0; i <4000; i++)
        {
            ImageSource img = path.GetIconFromFolder();
        }
stringpath=@“C:\Generic Folder\Generic Document.pdf”;

对于(int i=0;i您的
HANDLE
s已用完。Windows的句柄数量有限,当您获得一个句柄(在本例中为图标句柄)时,您需要在不再使用它后释放它。如果不使用,Windows将没有可用的句柄可供丢弃

如果SHGetFileInfo在psfi指向的SHFILEINFO结构的hIcon成员中返回一个图标句柄,您有责任在不再需要它时用DestroyIcon释放它

因此,您需要PInvoke并在函数结束时将
shinfo.hIcon
传递给它

处置使用
FromHandle
创建的图标不会破坏原始句柄:

使用此方法时,必须使用Win32 API中的DestroyIcon方法处理原始图标,以确保资源已释放


它是只在一个文件上出错还是每次都在另一个文件上出错?如果你只在该文件上运行它,它仍然会出错吗?你只是提醒我,我忘了在我的问题中添加一些内容,每次抛出异常时它可能是另一个文件,在以前成功的文件上它也可能失败,因此,这对我来说具有实际意义那么3311呢?直到您提到错误发生在不同的文件上之前,我一直假设没有。3311的意义在于,无论正在处理的文件之前是否成功,它似乎在第3311次失败。获取一个sysinternal工具,该工具可以跟踪句柄并在运行时观察进程的句柄计数ts正在运行。您几乎肯定是在某个地方泄漏句柄。它可能不在显示的代码中。图标的销毁不是通过Using语句处理的吗?我正在查看
图标
的源代码。
Dispose()
方法会销毁句柄。@艾米:当然,不管怎样,症状都是“句柄泄漏”都写在上面。OP应该得到一个探查器或一个可以跟踪进程拥有的句柄的sysinternal工具,以查看句柄计数的增加。@Amy
Dispose
方法调用一个名为
DestroyHandle
的内部方法,该方法仅在句柄拥有所有权时销毁句柄,而在构建if时不使用该方法从这里发生的现有句柄。调用DestroyIcon似乎已经解决了我测试线束中的问题。我已经将相同的逻辑应用到主应用程序中,并将在那里进行尝试。当然,如果它起作用,我会将此标记为答案。我想这可能是某个地方的泄漏,但我只是假设在使用wo结束时进行处理你能帮我处理吗