我尝试使用RestSharp从WCF / Rest服务下载图像。结果应保存在文件中,并显示在图像控件和WPF / SL页面中。
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没有返回预期的内存流。转移到另一个methed并以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我仍然得到错误:调用线程无法访问此对象,因为另一个线程拥有它。
答案 0 :(得分:4)
由于BitmapImage
是在除UI线程之外的另一个线程中创建的,因此您还必须调用Freeze
以便在UI线程中访问它。
虽然这里并非绝对必要,但最好始终处置任何IDisposable
个对象,包括MemoryStream
。因此,您还必须将BitmapImage.CacheOption
属性设置为OnLoad
。
using (var memoryStream = new MemoryStream(imageBytes))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze();
}
可以在UI线程中访问冻结的BitmapImage:
Dispatcher.Invoke((Action)(() => img.Source = bitmapImage));
答案 1 :(得分:0)
您是否使用调试器检查异常?如果后台任务抛出异常,除非您访问Task.Result
或使用await
运算符,否则不会在调用者代码中重新抛出异常。
我的猜测是您无权访问您要写的C:
位置。尽管如此,这段代码似乎是不必要的,您应该能够直接将图像源设置为您拥有的流,而无需将其写入磁盘。尝试评论写作以驱动一段代码,看看是否能解决问题。