【问题标题】:Converter Uri to BitmapImage - downloading image from web将 Uri 转换为 BitmapImage - 从 Web 下载图像
【发布时间】:2011-02-09 19:59:28
【问题描述】:

从 Uri 到 BitmapImage 的转换器有问题。 Uri 是网络上图像的 url。我在列表框中的项目上使用此转换器。

我从网页下载图片并从这个流 BitampImage 中创建

问题是如果列表框包含大约 100 - 250 个项目,应用程序冻结,我尝试在另一个线程中调用 WebRequestMethod 但它不起作用。

这是代码的根部分:

private static BitmapImage GetImgFromAzet(int sex, Uri imgUri)
{
    try
    {
        if (imgUri == null)
        {
            if (sex == (int)Sex.Man)
            {
                return new BitmapImage(new Uri(@"pack://application:,,,/Spirit;Component/images/DefaultAvatars/man.jpg",
                        UriKind.RelativeOrAbsolute));
            }
            else
            {
                return new BitmapImage(new Uri(@"pack://application:,,,/Spirit;Component/images/DefaultAvatars/woman.jpg",
                        UriKind.RelativeOrAbsolute));
            }
        }
        else
        {
            BitmapImage image = null;

            Task.Factory.StartNew(() =>
              {
                  WebRequest webRequest = WebRequest.CreateDefault(imgUri);
                  webRequest.ContentType = "image/jpeg";
                  WebResponse webResponse = webRequest.GetResponse();

                  image = new BitmapImage();
                  image.CreateOptions = BitmapCreateOptions.None;
                  image.CacheOption = BitmapCacheOption.OnLoad;
                  image.BeginInit();
                  image.StreamSource = webResponse.GetResponseStream();
                  image.EndInit();
                  return image;

                  //((System.Action)(() =>
                  //{


                  //    //webResponse.Close();

                  //})).OnUIThread();

              });

            return image;
        }
    }
    catch (Exception)
    {

//默认 返回 new BitmapImage(new Uri(PokecUrl.Avatar,UriKind.RelativeOrAbsolute)); } }

我的目标是从网上下载图像,从他那里创建 BitamImage 对象并作为图像源控件返回,但我需要避免应用程序冻结。还有一个问题是如果我关闭 webResponse 它会破坏所有代码。

已编辑:

我试试这个:

BitmapImage image;
WebRequest req = WebRequest.CreateDefault(imgUri);
req.ContentType = "image/jpeg";

using (var res = req.GetResponse())
{
        image = new BitmapImage();
        image.CreateOptions = BitmapCreateOptions.None;
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.BeginInit();
        image.UriSource = imgUri;
        image.StreamSource = res.GetResponseStream();
        image.EndInit();
}

但一定是某个地方有错误,代码被破坏了。

有什么建议吗?

【问题讨论】:

    标签: wpf httpwebrequest converter bitmapimage


    【解决方案1】:

    绑定转换器总是在 UI 线程上执行。因此,您可以在 Convert 方法中启动其他线程,但最终(因为您需要来自该线程的反馈)您必须等到它完成,从而阻止您的应用程序。

    为了解决这个问题,例如,你可以使用Binding.IsAsync property:

    public class ListItemViewData
    {
       private readonly Uri _uri;
       private readonly Sex _sex; 
    
       ListItemViewData(Uri uri, Sex sex)
       {
          this._uri = uri;
          this._sex = sex;
       }
    
       public BitmapSource Image
       {
           get
           {
               // Do synchronous WebRequest 
           }
       }
    }
    

    xaml 中的用法(在列表框项的 DataTemplate 内):

    <Image Source="{Binding Path=Image, IsAsync=True}"/>
    

    已编辑

    我深入研究了 BitmapImage 类,发现它有漂亮的 ctor 和 Uri 参数,可以异步工作。

    所以你不应该自己执行 WebRequest。这样做:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var uri = (Uri)value;
        return new BitmapImage(uri) { CacheOption = BitmapCacheOption.None };
    } 
    

    已编辑 2

    您的视图数据类。

    public class ListItemViewData : INotifyPropertyChanged
    {
        public ListItemViewData(Uri uri)
        {
            this._uri = uri;
        }
    
    private readonly Uri _uri;
    public Uri Uri
    {
        get 
        {
            return this._uri; 
        }
    }
    
    private BitmapSource _source = null;
    public BitmapSource Image
    {
        get
        {
            return this._source;
        }
        set 
        {
            this._source = value;
            this.OnPropertyChanged("Image");
        }
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string p)
    {
        var pc = this.PropertyChanged;
        if (pc!=null)
        { 
            pc(this, new PropertyChangedEventArgs(p));
        }
    }
    }
    

    Helper,执行图片下载:

    public static class WebHelper
    {
        public static Stream DownloadImage(Uri uri, string savePath)
        {
            var request = WebRequest.Create(uri);
            var response = request.GetResponse();
            using (var stream = response.GetResponseStream())
            {
                Byte[] buffer = new Byte[response.ContentLength];
                int offset = 0, actuallyRead = 0;
                do
                {
                    actuallyRead = stream.Read(buffer, offset, buffer.Length - offset);
                    offset += actuallyRead;
                }
                while (actuallyRead > 0);
                File.WriteAllBytes(savePath, buffer);
                return new MemoryStream(buffer);
            }
        }   
    }
    

    当您填充模型时 - 您应该启动单独的线程,该线程将下载文件并设置图像源。

    this._listItems.Add(new ListItemViewData(new Uri(@"http://lifeboat.com/images/blue.ocean.jpg")));
    //...
    var sc = SynchronizationContext.Current;
    new Thread(() =>
    {
        foreach (var item in this._listItems)
        { 
            var path = "c:\\folder\\"+item.Uri.Segments.Last();
            var stream = WebHelper.DownloadImage(item.Uri, path);
    
            sc.Send(p =>
                {
                    BitmapImage bi = new BitmapImage();
                    bi.BeginInit();
                    bi.StreamSource = (Stream)p;
                    bi.EndInit();
                    item.Image = bi;
                }, stream);
        }
    }).Start();
    

    【讨论】:

    • 您好,感谢反馈,我尝试使用异步绑定,但应用程序仍然冻结,问题一定是图片是从网站下载的,例如列表框有 200 个项目,转换器必须在 Web 服务器上创建 200 个请求-> 在我看来,这是问题的根源。你怎么看?
    • 我很困惑,我的目的是从网上下载图像并从他那里创建 BitmapImage。像这样stackoverflow.com/questions/2097152/…。从 MemoryStream 创建 BitmapImage 实例。
    • 感谢Zhevzhik先生,我尝试实施您的解决方案并相信它可以解决我的问题。
    猜你喜欢
    • 2010-10-06
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    相关资源
    最近更新 更多