首页 > 解决方案 > 我怎样才能给 Dispatcher.Invoke 一个论点?

问题描述

我正在尝试在后台线程中加载 BitmapImage,然后将(WPF)图像源设置为此 BitmapImage。

我目前正在尝试这样的事情:

public void LoadPicture()
{
    Uri filePath = new Uri(Directory.GetCurrentDirectory() + "/" + picture.PictureCacheLocation);
    if (Visible && !loaded)
    {
        if (File.Exists(filePath.AbsolutePath) && picture.DownloadComplete)
        {
            BitmapImage bitmapImage = LoadImage(filePath.AbsolutePath);
            image.Dispatcher.Invoke(new Action<BitmapImage>((btm) => image.Source = btm), bitmapImage);

            loaded = true;
        }
    }
}

但我得到一个InvalidOperationException,因为后台线程拥有 BitmapImage。有没有办法将 BitmapImage 的所有权或副本提供给 UI 线程?

我需要在后台线程中加载位图图像,因为它可能会阻塞很长时间。

标签: c#wpfmultithreadingbitmapimageinvalidoperationexception

解决方案


DependencyObject 的所有工作都应该在一个线程中进行。
除了 Freezable 的冻结实例。

将参数传递给 Invoke 也是没有意义的(在这种情况下) - 最好使用 lambda。

Dispatcher 也存在自锁的危险,因为您没有检查流。

    public void LoadPicture()
    {
        Uri filePath = new Uri(Directory.GetCurrentDirectory() + "/" + picture.PictureCacheLocation);
        if (Visible && !loaded)
        {
            if (File.Exists(filePath.AbsolutePath) && picture.DownloadComplete)
            {
                BitmapImage bitmapImage = LoadImage(filePath.AbsolutePath);

                bitmapImage.Freeze();

                if (image.Dispatcher.CheckAccess())
                    image.Source = bitmapImage;
                else
                    image.Dispatcher.Invoke(new Action(() => image.Source = bitmapImage));

                loaded = true;
            }
        }
    }

可冻结类型的对象并不总是允许自己被冻结。
但是您的代码不足以识别可能的问题。
如果你冻结失败,那么展示LoadImage(Uri)方法是如何实现的。


推荐阅读