2013-11-29 4 views
0

В моем текущем проекте мне нужно загрузить файл из Интернета один раз и использовать его в своем приложении WPF позже. Я настроил этот ленивый шаблон загрузки, чтобы загрузить/инициализировать BitmapImage только по запросу приложения, но, несмотря на все мои усилия, я не могу заставить его работать. Проблема в том, что я получаю IOException, когда он пытается создать экземпляр BitmapImage.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

Хорошо, я получил эту работу, наконец, и это не так, как Клеменс сказал ..: (

Проблема в том, что ... (и я считаю, что это так), что 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"); 
     } 
1

Для этого не используйте Pack URI. Вместо того, чтобы использовать обычный файл URI, который ссылается на загруженный файл (где filename полный путь, как в вашем коде):

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

Хм, я не уверен, что получаю это. Я не ссылаюсь на загруженный файл, как на "pack: // siteOfOrigin: ,,, /" + filename? Например, я думал, что это проблема: / – Kreweta

Смежные вопросы