Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 在后台加载图像而不锁定文件_Wpf_Multithreading_Image - Fatal编程技术网

Wpf 在后台加载图像而不锁定文件

Wpf 在后台加载图像而不锁定文件,wpf,multithreading,image,Wpf,Multithreading,Image,我的应用程序在BackgroundWorker中加载大量图像以保持可用性。我的图像控件绑定到名为“ImageSource”的属性。如果为空,则在后台加载并再次引发 public ImageSource ImageSource { get { if (imageSource != null) { return imageSource; }

我的应用程序在BackgroundWorker中加载大量图像以保持可用性。我的图像控件绑定到名为“ImageSource”的属性。如果为空,则在后台加载并再次引发

    public ImageSource ImageSource
    {
        get
        {
            if (imageSource != null)
            {
                return imageSource;
            }

            if (!backgroundImageLoadWorker.IsBusy)
            {
                backgroundImageLoadWorker.DoWork += new DoWorkEventHandler(bw_DoWork);
                backgroundImageLoadWorker.RunWorkerCompleted +=
                    new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                backgroundImageLoadWorker.RunWorkerAsync();
            }

            return imageSource;
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        bitmap = new BitmapImage();
        bitmap.BeginInit();
        try
        {
              bitmap.CreateOptions = BitmapCreateOptions.DelayCreation;
              bitmap.DecodePixelWidth = 300;

              MemoryStream memoryStream = new MemoryStream();
              byte[] fileContent = File.ReadAllBytes(imagePath);
              memoryStream.Write(fileContent, 0, fileContent.Length);
              memoryStream.Position = 0;
              bitmap.StreamSource = memoryStream;                            

         }
         finally
         {
             bitmap.EndInit();
         }
        bitmap.Freeze();
        e.Result = bitmap;
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        BitmapSource bitmap = e.Result as BitmapSource;

        if (bitmap != null)
        {
            Dispatcher.CurrentDispatcher.BeginInvoke(
                (ThreadStart)delegate()
                {
                    imageSource = bitmap;
                    RaisePropertyChanged("ImageSource");
                }, DispatcherPriority.Normal);
        }
    }
到目前为止一切都很好,但我的用户可以更改有问题的图像。他们在OpenDialog中选择一个新图像,旧图像文件被新图像覆盖,并且再次引发ImageSource,从而再次加载具有相同文件名的新图像:

    public string ImagePath
    {
        get { return imagePath; }
        set
        {
            imagePath= value;
            imageSource = null;
            RaisePropertyChanged("ImageSource");
        }
    }
在某些系统上,覆盖旧文件会导致异常:

    "a generic error occured in GDI+" and "The process cannot access the file..."
我尝试了很多方法,比如使用BitmapCreateOptions.IgnoreImageCache和BitmapCacheOption.OnLoad加载。这会在加载时引发异常:

   Key cannot be null.
   Parameter name: key

如果我在UI线程上没有BackgroundWorker的情况下尝试这一点,那么效果很好。我做错什么了吗?难道不可能在后台加载图像,同时保持文件的解锁状态吗?

好吧,似乎上述所有方法都能奏效。我简化了这个问题的例子,但不知怎么的,我在路上把问题弄丢了


我在代码中看到的唯一区别是,图像本身的加载被委托给了一个特定的图像加载程序类,它以某种方式造成了问题。当我删除此依赖项时,错误消失。

请发布您的“这将导致对ImageSource的新调用,该调用将再次加载具有相同文件名的新图像”。你为什么又装了。为什么不直接使用你拥有的图像并覆盖文件?@BalamBalam这实际上只是在设置新(或现有)文件路径后再次调用RaisePropertyChanged(“ImageSource”)。如果我不再次加载ImageSource,只复制文件,则更改在UI中不可见,错误仍然发生。据我所知,复制新文件时会发生错误,因为我的应用程序将文件锁定在缓存中;和RaisePropertyChanged(“ImageSource”)?您是否可以将用户指定的文件加载到imageSource、RaisePropertyChanged(“imageSource”)(因为它不为null,所以将使用imageSource),然后使用后台线程将其加载到file.WriteAllBytes?感谢您的评论,但这会导致类似的异常。我现在有了一个解决这个由房子造成的问题的办法(见答案)。