none
RenderTargetBitmap的Render效率问题 RRS feed

  • 问题

  • 提问,原来在使用RenderTargetBitmap来Render界面的时候,速度相当快,但是现在不知道怎么回事,忽然变得很慢很慢。

    原来大概在1秒以下可以Render结束,现在需要5秒。

    请问,这一般情况下是出于什么原因。

    运行环境是

    Celeron 2.2G

    2GB内存

    集显

    便以环境vs2008.

    private RenderTargetBitmap DoRenderBitmap(FrameworkElement element)
        {
          const double topLeft = 0;
          const double topRight = 0;
          const double dpiX = 96;
          const double dpiY = 96;
          int width = (int)element.ActualWidth;
          int height = (int)element.ActualHeight;
          DateTime dateTime = DateTime.Now;
          PixelFormat pixelFormat = PixelFormats.Default;
          VisualBrush elementBrush = new VisualBrush(element);
          DrawingVisual visual = new DrawingVisual();
          DrawingContext dc = visual.RenderOpen();
          Console.WriteLine(string.Format(@"{0}==========>RenderOpen", DateTime.Now.Subtract(dateTime)));
          dc.DrawRectangle(elementBrush, null, new Rect(topLeft, topRight, width, height));
          dc.Close();
          Console.WriteLine(string.Format(@"{0}==========>Close", DateTime.Now.Subtract(dateTime)));
    
          RenderTargetBitmap bitmap = new RenderTargetBitmap(width, height, dpiX, dpiY, pixelFormat);
          RenderOptions.SetBitmapScalingMode(bitmap, BitmapScalingMode.LowQuality);
          Console.WriteLine(string.Format(@"{0}==========>bitmap", DateTime.Now.Subtract(dateTime)));
          bitmap.Render(visual);
          Console.WriteLine(string.Format(@"{0}==========>Render", DateTime.Now.Subtract(dateTime)));
          return bitmap;
        }
    

    2010年11月25日 8:05

全部回复

  • 有一个前提忘记说了。

    开始的时候,我element上面的图片,是保存在文件中的。基本Render不需要什么时间。

    但是后来我改成放在内存中了,没有对应的文件,这个时候Render需要很长时间。

    请问这是什么原因呢?

    2010年11月25日 9:00
  • 有一个前提忘记说了。

    开始的时候,我element上面的图片,是保存在文件中的。基本Render不需要什么时间。

    但是后来我改成放在内存中了,没有对应的文件,这个时候Render需要很长时间。

    请问这是什么原因呢?


    你好,

    请问您是如何将文件保存在内存中,是否可以分享一些代码,然后我们可以帮助你调试?

    您是否使用一些性能调试工具进行了基本的检测,是否是render的性能还是 I/O 操作的性能慢导致?

    谢谢!

    致,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年11月26日 12:06
    版主
  • 首先,那个elements的层次结构如下: <WrapPanel> <Box/> <------我放了九个,也就是说那个Render渲染了9次。 </WrapPanel> <Box> <Grid> <Image Source={"Binding ImageData"}></Image> </Grid> </Box> Box.ImageData <--保存在属性中 而ImageData是一大堆数据,保存在一个Directory<string, BitmapImage>中,string是id 测试数据是直接用DateTime.Now来计算的,就像上面代码里面的Console输出一样。 保存在内存中的时候,读取时间输出是00:00:00,但是在Render的时候,使用了00:00:04~05. 而作为文件保存的时候,Render时间大概是0.x秒。 我不明白的地方是,怎么会每个有4秒的巨大差距。
    2010年11月26日 16:50
  • 你好,

    你可以尝试下设置 BitmapImage.CacheOption 属性到 OnLoad 值,这样每次的图片请求都会从缓存中读取。还有,你也可以尝试设置 BitmapImage.CreateOptions 属性,来更改创建图片对象的选项。

    具体到时间上的差异,这里很难去猜测,不过你还是可以通过使用WPF Performance Tool 去监测这个程序来获得,可能是布局系统造成,也可能是控件属性造成,还有可能使数据邦定造成。

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年11月29日 9:59
    版主
  • 好的,我可以测试一下。WPF性能工具来检测,似乎没有什么特别的地方。但是在Render的地方确实很慢,这个不知道是因为什么。
    2010年12月1日 1:00
  • 一直没有重新做这个东西,现在想起来回去看了一下。

    我的问题里面,用的是RenderTargetBitmap,这个Bitmap是没有

    你可以尝试下设置 BitmapImage.CacheOption 属性到 OnLoad 值,这样每次的图片请求都会从缓存中读取。还有,你也可以尝试设置 BitmapImage.CreateOptions 属性,来更改创建图片对象的选项。

    再者,即使是我没有设置,我的问题是,为什么保存在文件中的图片,在使用Render的时候,会比保存在内存中的图片要快,同样的设置情况下。包包啊,你没看清楚我的问题你就回答了啊。

    2010年12月3日 9:16
  • 至于包包你说的设置BitmapImage.CacheOption,或者在另外一个话题中,

    http://social.msdn.microsoft.com/Forums/en/wpfprerelease/thread/e2ebf264-e087-4bfe-a69b-24c884675c80

    09年的时候已经否定了你的说法。

    只是我比较纠结的是为什么内存操作会比文件操作慢。

     

    2010年12月3日 9:51
  • 你好,

    对,按照理论来说,内存是不会比文件系统的I/O慢的,但是,很多时候是由于其它具体的因素造成了性能的消耗。你这个问题我试着去重现,现在我比较疑惑的是,那个图片你是如何读入到内存的?是否有大量的时间浪费在了绑定系统的更欣上,而读文件会绕过Image.Source="{Binding ...}"数据绑定,直接将数据传给Render.

    还有一个建议,是否可以测试下把图像数据读到一个属性里面,然后做绑定,而不是读取一堆图像放入一个Dictionary集合。这样测试具有针对性,可以避免一些由于Dictionary操作造成的性能损失!

    Sincerely,
    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Are you looking for a typical code sample? Please download All in One Code Framework !

    如果有回复帮助并解决了您的问题,请点击 “标记为答复”,如果没有没有帮助,请随时点击“取消答复标记”
    你在为寻找代码示例而苦恼吗?赶快来下载 All in One Code Framework 微软一站式代码框架 吧!
    2010年12月6日 6:07
    版主
  • 谢谢回复,

    在程序里面没有使用到xaml里面的绑定,而是直接image.Source = BitmapImage

    用dictionary的缘故,是因为机器本身硬件条件差,而列表中的数据量大,如果直接绑定到属性上保存的话,又会发生我另外一个话题里面的,Scroll里面大量数据的时候性能大幅下降,怎么办,这样一个问题。

    由于不能用原图,所以使用缩略图。用内存和用文件保存缩略图的唯一区别,在于第一次读入原图的时候,检查缩略图有没有生成。如果没有生成,内存是以 id,BitmapImage保存到Dictionary,文件是以id为文件名,BitmapImage.Save保存。按理说,Dictionary的操作损失的性能,应该没有读文件来的慢。并且测试时候的慢点,在于Render,这个时候,数据已经读取出来了,已经在Image控件的Source里面了。

    是否Render的内部的机制问题?在Render Visual的时候,是怎么作镜像的?

     

    2010年12月7日 10:33