title: Loading a web image asynchronously
body: <p>I've encountered a problem with displaying an image from the web in my WPF app:</p>
  
  <p>I used a <code>BitmapImage</code> for this task. My first attempt was to execute it in the UI thread but I quickly understood that's a no-no since the application became unresponsive until the image was completely loaded. My second attempt was to use a <code>BackgroudWorker</code>:</p>
  
  <pre><code>var worker = new BackgroundWorker();
  worker.DoWork += worker_LoadImage;
  worker.RunWorkerCompleted+=worker_RunWorkerCompleted;
  worker.RunWorkerAsync(someURI);
  </code></pre>
  
  <p>and the worker functions:</p>
  
  <pre><code>    private void worker_LoadImage(object sender, DoWorkEventArgs e)
      {
          var image = new BitmapImage(); 
          image.BeginInit();
          image.CacheOption = BitmapCacheOption.OnDemand;
          image.UriSource = e.Argument as Uri;
          image.DownloadFailed += new EventHandler&lt;ExceptionEventArgs&gt;(image_DownloadFailed);
          image.EndInit();
          e.Result = image;
      }
  
      void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
          //if I understand correctly, this code runs in the UI thread so the 
          //access to the component image1 is valid.
          image1.Source = e.Result as BitmapImage;
      }
  </code></pre>
  
  <p>after that, I still got an InvalidOperationException: "The calling thread cannot access this object because a different thread owns it."
  I've researched a bit and found out that since <code>BitmapImage</code> is <code>Freezable</code>, I have to call <code>Freeze</code> before accessing the object from another thread. 
  So I've tried to replace the last row in worker_LoadImage with: </p>
  
  <pre><code>        image.Freeze();
          e.Result = image;
  </code></pre>
  
  <p>But then I got an exception that my image cannot be frozen, I found out that it's probably
  because the image wasn't done being downloaded when I tried to invoke <code>Freeze()</code>. So I added the following code to the image creation:</p>
  
  <pre><code>        image.DownloadCompleted += image_DownloadCompleted;
  </code></pre>
  
  <p>where:</p>
  
  <pre><code> void image_DownloadCompleted(object sender, EventArgs e)
   {
       BitmapImage img = (BitmapImage)sender;
       img.Freeze();
   }
  </code></pre>
  
  <p>So now we get to the real question:
  <strong>How do I make the background worker to wait until the image is completely downloaded and the event is fired?</strong></p>
  
  <p>I've tried many things: looping while the image's isDownloading is true, Thread.Sleep, Thread.Yield, Semaphores, Event wait handles and more.
  I dont know how the image downloading actually works behind the scenes but what happens when I try one of the methods above is that the image never finishes to download (isDownloading is stuck on True)</p>
  
  <p>Is there a better, simpler way to achieve the rather simple task im trying to accomplish?</p>
  
  <p>Some things to notice:</p>
  
  <ol>
  <li><p><a href="https://stackoverflow.com/questions/5439042/loading-an-image-in-a-background-thread-in-wpf/5444654#5444654">this answer</a> actually works, but only once: when I try to load another image it says the dispatcher is closed. Even after reading a bit about Dispatchers, I don't really understand how the OP achieved that or if it's possible to extend the solution for more than one image.</p></li>
  <li><p>When I put a message box before the worker exits his DoWork function, I click OK and the image apears which means the download continued while the message box was opened and finished before I clicked OK.</p></li>
  </ol>