3

我正在尝试使用 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 没有返回预期的内存流。转移到另一种方法并以 byte[] 格式访问原始数据可以解决部分问题,将图片保存到磁盘。

    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 我仍然得到错误:调用线程无法访问这个对象,因为不同的线程拥有它。

4

2 回答 2

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();
}

冻结的 BitmapImage 可在 UI 线程中访问:

Dispatcher.Invoke((Action)(() => img.Source = bitmapImage));
于 2013-02-24T19:51:54.220 回答
0

您是否使用调试器检查异常?Task.Result如果在后台任务上引发异常,除非您访问或使用运算符,否则不会在调用者代码上重新引发异常await

我的猜测是您无权访问C:您正在写入的位置。无论如何,该代码块似乎没有必要,您应该能够直接将图像的源设置为您拥有的流,而无需将其写入磁盘。尝试评论写作以驱动一段代码,看看是否能解决问题。

于 2013-02-24T16:40:14.797 回答