RestSharp - 在WPF / Silverlight中下载/使用图像

时间:2013-02-24 16:25:03

标签: wpf image silverlight download restsharp

我尝试使用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我仍然得到错误:调用线程无法访问此对象,因为另一个线程拥有它。

2 个答案:

答案 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:位置。尽管如此,这段代码似乎是不必要的,您应该能够直接将图像源设置为您拥有的流,而无需将其写入磁盘。尝试评论写作以驱动一段代码,看看是否能解决问题。