我有图像控件,可以在不同的线程中加载图标
它通常可以工作但是对于某些文件扩展名(xml,html ...),如果在后台线程中检索它,它总是返回默认图标,但在UI线程上检索时是正确的图标。
为什么会这样?
void cIconImage_Loaded(object sender, RoutedEventArgs e)
{
var source = GetImage(mypath);
this.Source = source;
}
private ImageSource GetImage(string mypath)
{
ImageSource imgSource = null;
icon = ShellIcon.GetSmallIcon(mypath);
imgSource = icon.ToImageSource();
imgSource.Freeze();
return imgSource;
}
private static Icon GetIcon(string fileName, SHGFI flags, bool isFolder = false)
{
SHFILEINFO shinfo = new SHFILEINFO();
//////For some extensions (xml, html,...) returns default icon
var task = Task.Factory.StartNew(() =>
Win32.SHGetFileInfo(fileName, isFolder ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL, ref shinfo, (uint)Marshal.SizeOf(shinfo), (uint)(SHGFI.Icon | flags))
);
task.Wait(); //temporary
//////Everything OK but not in background thread
IntPtr hImgSmall = Win32.SHGetFileInfo(fileName, isFolder ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL, ref shinfo, (uint)Marshal.SizeOf(shinfo), (uint)(SHGFI.Icon | flags));
//////
Icon icon = (Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone();
Win32.DestroyIcon(shinfo.hIcon);
return icon;
}
GetIcon是此课程https://gist.github.com/madd0/1433330的一部分 但我尝试过这个类的许多不同变体,结果相同。
答案 0 :(得分:0)
这似乎有用,并显示所有图标
void cIconImage_Loaded(object sender, RoutedEventArgs e)
{
var thread = new System.Threading.Thread(() =>
{
CoInitialize((IntPtr)0);
var source = GetImage(mypath);
this.Dispatcher.BeginInvoke(new Action(() =>
{
this.Source = source;
}), System.Windows.Threading.DispatcherPriority.Background);
CoUninitialize();
});
thread.IsBackground = true;
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
}
其他一切都是一样的(除了GetIcon不使用Task.Factory)
答案 1 :(得分:0)
您需要指定该线程是单线程单元。您可以在线程启动之前调用SetApartmentState(System.Threading.ApartmentState.STA)
来执行此操作。请注意,您不应该致电CoInitialize
或CoInitializeEx
,因为这将自动为您完成。有关详细信息,请参阅此优秀问题:Do i need to call CoInitialize before interacting with COM in .NET?
要做的另一点是SHGetFileInfo
不是线程安全的。如果您有多个线程调用SHGetFileInfo
,则需要将这些调用序列化为SHGetFileInfo
。