Reputation: 55
I'm trying to use RestSharp to download an image from a WCF/Rest service. The result should be saved in a file and displayed in a Image control an a WPF/SL page.
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;
}
});
}
When I look in fiddler the image got downloaded correctly BUT no image is saved and nothing is displayd. There is no exception thown. ANy suggestions ?
UPDATED
A part of the problem turns out that RestSharp is not returning the expected memorystream. Moving to another methed and accessing the raw data in byte[] format solves part of the problem, saving the picutere to disk.
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; }));
;
}
});
}
Although calling this.dispatcher.Invoke I still get the error : The calling thread cannot acces this object because a different thread owns it.
Upvotes: 3
Views: 3741
Reputation: 128106
As the BitmapImage
is created in another thread than the UI thread, you also have to call Freeze
to make it accessible in the UI thread.
Although not strictly necessary here, it is good practise to always dispose of any IDisposable
objects, including MemoryStream
. Therefore you will also have to set the BitmapImage.CacheOption
property to OnLoad
.
using (var memoryStream = new MemoryStream(imageBytes))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze();
}
The frozen BitmapImage is accessible in the UI thread:
Dispatcher.Invoke((Action)(() => img.Source = bitmapImage));
Upvotes: 4
Reputation: 2586
Are you checking for exceptions using the debugger? If an exception is thrown on a background task, it won't be rethrown on the caller code unless you access Task.Result
or use the await
operator.
My guess is that you don't have access to the location of C:
you are writing to. That block of code seems unnecessary anyway though, you should be able to directly set the source of the image to the stream you have without writing it to disk. Try commenting the writing to drive piece of code out and see if that solves the issue.
Upvotes: 0