Loading an image in a background thread in WPF

后端 未结 2 1634
情深已故
情深已故 2020-12-31 02:35

There are a bunch of questions about this already on this site and other forums, but I\'ve yet to find a solution that actually works.

Here\'s what I want to do:

2条回答
  •  臣服心动
    2020-12-31 03:26

    The BitmapImage needs async support for all of its events and internals. Calling Dispatcher.Run() on the background thread will...well run the dispatcher for the thread. (BitmapImage inherits from DispatcherObject so it needs a dispatcher. If the thread that created the BitmapImage doesn't already have a dispatcher a new one will be created on demand. cool.).

    Important safety tip: The BitmapImage will NOT raise any events if it is pulling data from cache (rats).

    This has been working very well for me....

         var worker = new BackgroundWorker() { WorkerReportsProgress = true };
    
         // DoWork runs on a brackground thread...no thouchy uiy.
         worker.DoWork += (sender, args) =>
         {
            var uri = args.Argument as Uri;
            var image = new BitmapImage();
    
            image.BeginInit();
            image.DownloadProgress += (s, e) => worker.ReportProgress(e.Progress);
            image.DownloadFailed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown();
            image.DecodeFailed += (s, e) => Dispatcher.CurrentDispatcher.InvokeShutdown();
            image.DownloadCompleted += (s, e) =>
            {
               image.Freeze();
               args.Result = image;
               Dispatcher.CurrentDispatcher.InvokeShutdown();
            };
            image.UriSource = uri;
            image.EndInit();
    
            // !!! if IsDownloading == false the image is cached and NO events will fire !!!
    
            if (image.IsDownloading == false)
            {
               image.Freeze();
               args.Result = image;
            }
            else
            {
               // block until InvokeShutdown() is called. 
               Dispatcher.Run();
            }
         };
    
         // ProgressChanged runs on the UI thread
         worker.ProgressChanged += (s, args) => progressBar.Value = args.ProgressPercentage;
    
         // RunWorkerCompleted runs on the UI thread
         worker.RunWorkerCompleted += (s, args) =>
         {
            if (args.Error == null)
            {
               uiImage.Source = args.Result as BitmapImage;
            }
         };
    
         var imageUri = new Uri(@"http://farm6.static.flickr.com/5204/5275574073_1c5b004117_b.jpg");
    
         worker.RunWorkerAsync(imageUri);
    

提交回复
热议问题