在我当前的项目中,我需要从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
在下载完成之前被实例化,但是这里不应该使用互斥来防止这种行为?
答案 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");
}