BitmapImage无法访问该文件

时间:2013-11-29 09:54:33

标签: c# wpf asynchronous ioerror

在我当前的项目中,我需要从Internet下载文件一次,然后在我的WPF应用程序中使用它们。我已经设置了这个延迟加载模式,以便仅在应用程序请求时下载/初始化BitmapImage,但尽管我尽了最大的努力,但我无法使其工作。问题是我在尝试实例化IOException时得到BitmapImage

下面我发布一个完整的应用程序,你可以自己运行并遇到同样的问题......

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        string url = @"http://upload.wikimedia.org/wikipedia/commons/d/d3/Nelumno_nucifera_open_flower_-_botanic_garden_adelaide2.jpg";
        string filename = "PrettyFlower.jpg";
        Mutex m = new Mutex();
        bool isLoaded = false;
        BitmapImage flowerImage = null;

        public MainWindow()
        {
            InitializeComponent();

            Binding b = new Binding("FlowerImage");
            b.Source = this;
            img.SetBinding(Image.SourceProperty, b);
        }

        public BitmapImage FlowerImage 
        {
            get
            {
                if (isLoaded == false)
                {
                    LoadImage();
                    return null;
                }
                return flowerImage;
            }
        }

        private async void LoadImage()
        {
            WebClient wc = new WebClient();
            m.WaitOne();

            FileInfo fi = new FileInfo(filename);
            if (fi.Exists == false)
            {
                await wc.DownloadFileTaskAsync(url, filename);
            }

            flowerImage = new BitmapImage(new Uri("pack://siteOfOrigin:,,,/" + filename));
            isLoaded = true;
            OnPropertyChanged("FlowerImage");

            m.ReleaseMutex();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

相应的MainWindow.xaml仅此而已:

<Window x:Class="WpfApplication1.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">
   <Image x:Name="img"/>
</Window>

我确实注意到了什么,但老实说我不明白为什么会发生这种情况 - 也就是说,BitmapImage在下载完成之前被实例化,但是这里不应该使用互斥来防止这种行为?

2 个答案:

答案 0 :(得分:1)

您不会使用Pack URI。而是使用引用下载文件的纯文件URI(其中filename是代码中的完整路径):

flowerImage = new BitmapImage(new Uri(filename));

答案 1 :(得分:0)

好的,我终于让它工作了,这不像克莱门斯说的那样...... :(

问题似乎是......(而且我相信)LoadImage在调用wc.DownloadFileTaskAsync之前不会启动另一个线程。这是唯一一个在另一个线程中运行的东西,因此......对WaitOne()的调用完全是愚蠢的,因为互斥量是由UI线程声明的......

我开始工作的方式是......

private async void LoadImage()
        {
            WebClient wc = new WebClient();

            await Task.Run(() =>
                {
                    m.WaitOne();

                    FileInfo fi = new FileInfo(filename);
                    if (fi.Exists == false)
                    {
                        wc.DownloadFile(url, filename);
                        wc.Dispose();
                    }

                    m.ReleaseMutex();
                });

            m.WaitOne();
            flowerImage = new BitmapImage(new Uri("pack://siteOfOrigin:,,,/" + filename));
            m.ReleaseMutex();

            isLoaded = true;
            OnPropertyChanged("FlowerImage");
        }