使用AsParallel()时无法获取与Windows应用程序关联的文件的文件图标

Ste*_*ann 5 .net c# windows wpf plinq

我想显示与文件相关的图标.对于与普通桌面应用程序关联的文件类型,这不是问题,但仅适用于与(metro/modern)应用程序关联的文件类型.

如果文件类型我正在使用的应用程序相关联AsParallel(),我只会获得默认的未知文件类型图标.为了澄清,我没有得到null或是一个空图标,而是显示空纸张的默认图标.没有AsParallel()我得到正确的图标.

我尝试了其他几种方法来获取图标,例如,SHGetFileInfo()ExtractAssociatedIcon()通过dll直接调用.行为总是一样的.

示例:如果"Adobe Acrobat"是PDF文件的默认应用程序,则在这两种情况下都会获得正确的Adobe PDF图标.如果Windows 8或10中的内置(现代UI)应用程序"Reader"是默认应用程序,AsParallel()则应用时会显示未知文件类型图标.

MCVE

XAML:

<Window x:Class="FileIconTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox x:Name="TxtFilename" Text="x:\somefile.pdf"/>
        <Button Click="Button_Click">Go</Button>
        <Image x:Name="TheIcon" Stretch="None"/>
    </StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

对应代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var list = new List<string>();
    list.Add(TxtFilename.Text);

    var icons = list.AsParallel().Select(GetIcon); // problem with apps
//  var icons = list.Select(GetIcon);              // works always
    TheIcon.Source = icons.First();
}

public static ImageSource GetIcon(string filename)
{
    var icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
    var iSource = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty,
        BitmapSizeOptions.FromEmptyOptions());
    iSource.Freeze();
    return iSource;
}
Run Code Online (Sandbox Code Playgroud)

使用说明:仅使用两种变体中的一种.如果两者都被执行,即使使用不同的变量,问题也可能无法重现.

Tho*_*que 4

这是因为SHGetFileInfo(或ExtractAssociatedIcon,内部使用SHGetFileInfo)仅适用于 STA 线程(单线程单元)。在 MTA 线程(多线程单元)上,它仅返回默认图标。AsParallel使用线程池中的工作线程,即 MTA。