正确的方式来处理图像/位图和图片框
我正在尝试开发Windows Mobile 6(在WF / C#中)应用程序。 只有一个窗体,窗体上只有一个PictureBox对象。 在这上面我画了所有想要的控件或任何我想要的。
我正在做两件事。 绘制自定义形状并从.png文件加载位图。
下一行在加载时locking文件(这是一个不希望的情况):
Bitmap bmp = new Bitmap("file.png");
所以我正在使用另一种方式来加载位图。
public static Bitmap LoadBitmap(string path) { using (Bitmap original = new Bitmap(path)) { return new Bitmap(original); } }
这是我猜得慢得多,但我不知道有更好的方式来加载图像,同时快速释放文件locking。
现在,当绘制图像时,我使用的方法是:
public void Draw() { Bitmap bmp = new Bitmap(240,320); Graphics g = Graphics.FromImage(bmp); // draw something with Graphics here. g.Clear(Color.Black); g.DrawImage(Images.CloseIcon, 16, 48); g.DrawImage(Images.RefreshIcon, 46, 48); g.FillRectangle(new SolidBrush(Color.Black), 0, 100, 240, 103); pictureBox.Image = bmp; }
这似乎是某种内存泄漏。 如果我一直这样做,应用程序最终会崩溃。
所以我有三个问题:
1.)什么是从文件加载位图而不locking文件的更好的方法?
2)什么对象需要手动处理的Draw()函数(以什么顺序),所以没有内存泄漏,没有ObjectDisposedException抛出?
3.)如果pictureBox.Image被设置为bmp,就像在代码的最后一行一样,将pictureBox.Image.Dispose()只处理与维护pictureBox.Image或底层Bitmap相关的资源吗?
1:我不知道它是否在WM工作,但试试这个:
FileStream bitmapFile = new FileStream("mybitmap.bmp", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); Image loaded = new Bitmap(bitmapFile);
2:必须处理SolidBrush
。 处理有一个通用的规则。 – >“由你实例化的每个对象,实现configuration必须手动configuration,当对象是一个return / ref / out值时,
在这种情况下,最好使用using
语句
using (new objecttodispose){ ..... }
using
语句将确保在任何情况下调用Dispose()
(例如exception)。
3: Dispose()
将释放位图资源。
我不认为有真正的内存泄漏 。 问题是,你不处理旧的位图,这是由GC来清理的东西。 但是没有确定性的方式来说明什么时候会发生。
所以我认为如果你要循环播放大量的图片,你会看到一些记忆力的增加,而在其他的一些情况下,它会下降或抵制一个位置。
我没有对它进行testing,但也许这会有助于使其更确定:
public void Draw() { Bitmap bmp = new Bitmap(240,320); using(var g = Graphics.FromImage(bmp)) using(var solidBrush = SolidBrush(Color.Black)) { // draw something with Graphics here. g.Clear(Color.Black); g.DrawImage(Images.CloseIcon, 16, 48); g.DrawImage(Images.RefreshIcon, 46, 48); g.FillRectangle(solidBrush, 0, 100, 240, 103); //Backup old image in pictureBox var oldImage = pictureBox.Image; pictureBox.Image = bmp; //Release resources from old image if(oldImage != null) ((IDisposable)oldImage).Dispose(); } }
更新
还有另一个灵感来自jack30lena的想法:
public static Bitmap LoadBitmap(string path) { //Open file in read only mode using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) //Get a binary reader for the file stream using (BinaryReader reader = new BinaryReader(stream)) { //copy the content of the file into a memory stream var memoryStream = new MemoryStream(reader.ReadBytes((int)stream.Length)); //make a new Bitmap object the owner of the MemoryStream return new Bitmap(memoryStream); } }
我的第二个代码示例背后的想法是摆脱文件句柄,并将文件内容复制到内存中。 之后,位图将通过调用oldImage.Dispose()
来获取将放置在我的第一个示例中的MemoryStream的所有权。
通过使用这种方法,内存中永远不应该有两个以上的图像,只有通过真正大的图像或less量的RAM才能导致OutOfMemoryExceptionexception。