2013-02-24 2 views
3

Я пытаюсь использовать RestSharp для загрузки изображения из службы WCF/Rest. Результат должен быть сохранен в файле и отображен в элементе управления изображением на странице WPF/SL.RestSharp - Загрузка/использование изображения в WPF/Silverlight

private void GetImage() 
    { 
     RestClient _Client = new RestClient(BASE_URI); 
     RestRequest request = new RestRequest("/api/img/{FileName}"); 
     request.AddParameter("FileName", "dummy.jpg", ParameterType.UrlSegment); 
     _Client.ExecuteAsync<MemoryStream>(
     request, 
     Response => 
     { 
      if (Response != null) 
      { 
       var bitmapImage = new BitmapImage(); 
       bitmapImage.BeginInit(); 
       bitmapImage.StreamSource = Response.Data; 
       String fn = String.Format(@"c:\temp\{0}.jpg", Guid.NewGuid().ToString()); 
       System.IO.File.WriteAllBytes(fn,Response.Data.ToArray()); 
       bitmapImage.EndInit(); 
       img.Source = bitmapImage; 
      } 
     }); 
    } 

Когда я смотрю в скрипаче, изображение загрузилось правильно, но изображение не сохраняется, и ничего не отображается. Исключено исключение. Какие-либо предложения ?


ОБНОВЛЕНО

Часть проблемы оказывается, что RestSharp не возвращает ожидаемый MemoryStream. Переход к другому методу и доступ к необработанным данным в формате byte [] решает часть проблемы, сохраняя picutere на диск.

private void GetImage() 
    { 
     RestClient _Client = new RestClient(BASE_URI); 
     RestRequest request = new RestRequest("/api/img/{FileName}"); 
     request.AddParameter("FileName", "dummy.jpg", ParameterType.UrlSegment); 
     _Client.ExecuteAsync(
     request, 
     Response => 
     { 
      if (Response != null) 
      { 
       byte[] imageBytes = Response.RawBytes; 
       var bitmapImage = new BitmapImage(); 
       bitmapImage.BeginInit(); 
       bitmapImage.StreamSource = new MemoryStream(imageBytes); 
       bitmapImage.CreateOptions = BitmapCreateOptions.None; 
       bitmapImage.CacheOption = BitmapCacheOption.Default; 
       bitmapImage.EndInit(); 

       JpegBitmapEncoder encoder = new JpegBitmapEncoder(); 
       Guid photoID = System.Guid.NewGuid(); 
       String photolocation = String.Format(@"c:\temp\{0}.jpg", Guid.NewGuid().ToString()); 
       encoder.Frames.Add(BitmapFrame.Create(bitmapImage)); 
       using (var filestream = new FileStream(photolocation, FileMode.Create)) 
       encoder.Save(filestream); 

       this.Dispatcher.Invoke((Action)(() => { img.Source = bitmapImage; })); 
       ; 
      } 
     }); 
    } 

Хотя вызов this.dispatcher.Invoke я все еще получаю ошибку: Вызывающий поток не может Acces этого объекта, потому что другой поток владеет.

ответ

4

Поскольку BitmapImage создан в другом потоке, кроме потока пользовательского интерфейса, вам также необходимо позвонить Freeze, чтобы сделать его доступным в потоке пользовательского интерфейса.

Несмотря на то, что это не является абсолютно необходимым, рекомендуется всегда удалять любые объекты IDisposable, включая MemoryStream. Поэтому вам также необходимо будет установить BitmapImage.CacheOption на OnLoad.

using (var memoryStream = new MemoryStream(imageBytes)) 
{ 
    bitmapImage.BeginInit(); 
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
    bitmapImage.StreamSource = memoryStream; 
    bitmapImage.EndInit(); 
    bitmapImage.Freeze(); 
} 

Замороженный BitmapImage доступен в потоке пользовательского интерфейса:

Dispatcher.Invoke((Action)(() => img.Source = bitmapImage)); 
+0

upadted вопрос – Brilbroeder

+0

Обновленный ответ тоже. Обратите внимание, что по-прежнему необходимо установить «BitmapCacheOption.OnLoad». – Clemens

+0

Thx. Недостатком является .Freeze(). – Brilbroeder

0

Вы проверяете исключения с помощью отладчика? Если исключение выбрано в фоновом задании, оно не будет возвращено на код вызывающего абонента, если вы не получите доступ к Task.Result или не используйте оператор await.

Я предполагаю, что у вас нет доступа к адресу C:, о котором вы пишете. Тем не менее, этот блок кода кажется ненужным, но вы должны иметь возможность напрямую установить источник изображения в поток, который у вас есть, не записывая его на диск. Попробуйте комментировать запись, чтобы вывести фрагмент кода и посмотреть, решит ли это проблему.

+0

обновленный вопрос – Brilbroeder