C# 在单独线程上创建并冻结的BitmapImage不显示

C# 在单独线程上创建并冻结的BitmapImage不显示,c#,wpf,bitmapimage,C#,Wpf,Bitmapimage,我有一个图像,其中源绑定到视图模型位图图像属性。它是在树状视图中为每个树状视图项显示的图标。我想在一个单独的线程中加载图像,以减少树初始化期间UI线程的阻塞 我读过类似问题的各种答案,但我还没有找到解决这个问题的方法。我知道,要使位图图像跨线程可用,必须冻结图像,但正是这种冻结停止了图像的渲染 我按如下方式加载图像: private void LoadImage() { Task.Run(() => { if (string.IsNullOrWhiteSpa

我有一个
图像
,其中
绑定到视图模型
位图图像
属性。它是在树状视图中为每个树状视图项显示的图标。我想在一个单独的线程中加载图像,以减少树初始化期间UI线程的阻塞

我读过类似问题的各种答案,但我还没有找到解决这个问题的方法。我知道,要使
位图图像跨线程可用,必须
冻结
图像,但正是这种冻结停止了图像的渲染

我按如下方式加载图像:

private void LoadImage()
{
    Task.Run(() =>
    {
        if (string.IsNullOrWhiteSpace(_imagePath))
            return ;
        string[] resources = GetResourceNames();
        var result = resources?.FirstOrDefault(x => String.Equals(x, _image, StringComparison.CurrentCultureIgnoreCase)) ??
                     resources?.FirstOrDefault(x => String.Equals(Path.GetFileName(x), _imagePath, StringComparison.CurrentCultureIgnoreCase));
        var image = result == null ? null : new BitmapImage(GetUri(ImageResourceCache.ImagesAssembly.FullName, result));
        if (image == null) return;

        image.CacheOption = BitmapCacheOption.OnLoad; //<== a suggested solution that does not make a difference
        image.Freeze();//<== freezing stops the cross thread exception but stops rendering

        DispatcherHelp.CheckInvokeOnUI(() => Image = image);
    });
}

private static string[] GetResourceNames()
{
    var asm = ImageResourceCache.ImagesAssembly;
    var resName = asm.GetName().Name + ".g.resources";
    using (var stream = asm.GetManifestResourceStream(resName))
    {
        if (stream == null) return null;
        using (var reader = new ResourceReader(stream))
            return reader.Cast<DictionaryEntry>().Select(entry => (string)entry.Key).ToArray();
    }
}

private static Uri GetUri(string dllName, string relativeFilePath)
{
    return new Uri($"/{dllName};component/{relativeFilePath}", UriKind.RelativeOrAbsolute);
}
<Image Source="{Binding Image}" Stretch="Uniform" Margin="0 0 3 0" />
视图模型:

public BitmapImage Image
{
    get => _image;
    set
    {
        _image = value;
        RaisePropertyChanged();
    }
}
您应该使用a来识别图像资源。如果有image/pic.jpeg资源,这应该可以工作:

Task.Run(() =>
{
    BitmapImage image = new BitmapImage(new Uri("pack://application:,,,/images/pic.jpeg", UriKind.RelativeOrAbsolute));
    image.Freeze();
    Dispatcher.BeginInvoke(new Action(() => Image = image));
});

您的
GetUri
方法似乎缺少
pack://application:,,,/
零件。当您可以使用包URI时,没有理由像当前一样查找资源。

LoadImage在构造函数中被调用,您是否尝试在主线程中创建它?也许图像不能显示这个流不,我在一个单独的线程(Task.Run)中创建它,因此需要冻结image@TimRutter能否尝试设置图像控件的源代码?不使用bind.Image属性是请参见上文-提升属性已更改。DispatcherHelp.CheckInvokeOnUI-检查当前线程上下文是否为ui线程,如果不是,则在主线程上调用它。这是必需的,否则会引发异常,原因是另一个线程拥有“无法访问”对象it@lindexi:以上代码对我来说很好。包URI可以在任何线程上工作。所以我说
可能
@lindexi:因为
pack://application:
Uri中缺少、、、/
。就是这样,谢谢。我补充说pack://application:,,,/到GetUri,它就工作了。你是对的,我不需要循环使用资源。这实际上是用来加载DevExpress图像的,我想这是他们发给我的代码。