在进行PDA开发时,我从Sqlite数据库中动态读取图片并显示,一开始没有问题,可以重复运行几次后提示outofmemoryexception错误。希望高手们给予帮助。谢谢!
具体代码如下:tc_TP是tabcontrol控件
tc_TP.TabPages.Clear();
string selsql = "Select * From T_NoteBookTP Where DH = '" + tb_XDH.Text.Trim() + "'";
DataSet ds = SqliteHelper.ExecuteDataset(selsql.Trim());
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
byte[] data = (byte[])dr["TP"];
if (data.Length > 0)
{
MemoryStream myStream = new MemoryStream();
foreach (byte a in data)
{
myStream.WriteByte(a);
}
System.Drawing.Bitmap bmp = new Bitmap(myStream);
myStream.Close();
Image myImage = Image.FromHbitmap(bmp.GetHbitmap());
//动态生成tab页
TabPage tp = new TabPage();
tp.Text = dr["TPMC"].ToString().Trim();
//动态生成picturebox,并加载照片信息
PictureBox pb = new PictureBox();
pb.Dock = DockStyle.Fill;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Image = myImage;
//动态添加照片和tab页
tp.Controls.Add(pb);
tc_TP.TabPages.Add(tp);
bmp.Dispose();
}
}
}
具体代码如下:tc_TP是tabcontrol控件
tc_TP.TabPages.Clear();
string selsql = "Select * From T_NoteBookTP Where DH = '" + tb_XDH.Text.Trim() + "'";
DataSet ds = SqliteHelper.ExecuteDataset(selsql.Trim());
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
byte[] data = (byte[])dr["TP"];
if (data.Length > 0)
{
MemoryStream myStream = new MemoryStream();
foreach (byte a in data)
{
myStream.WriteByte(a);
}
System.Drawing.Bitmap bmp = new Bitmap(myStream);
myStream.Close();
Image myImage = Image.FromHbitmap(bmp.GetHbitmap());
//动态生成tab页
TabPage tp = new TabPage();
tp.Text = dr["TPMC"].ToString().Trim();
//动态生成picturebox,并加载照片信息
PictureBox pb = new PictureBox();
pb.Dock = DockStyle.Fill;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Image = myImage;
//动态添加照片和tab页
tp.Controls.Add(pb);
tc_TP.TabPages.Add(tp);
bmp.Dispose();
}
}
}
我建议你用动态加载,利用tabcontrol每次只会显示当前页的特点,当切换页时把除当前页的图片全部卸载。
如果再考虑得全面点,每次读取到图片就保存到本地,切换时先从本地找,找不着再从数据库里拿。
是在这一步出的错System.Drawing.Bitmap bmp = new Bitmap(myStream);
保存到本地的方法我也试过,也是同样的错误。
{
tc_TP.TabPages.Clear();
OpenFileDialog open = new OpenFileDialog();
open.Filter = "图片|*.jpg";
if (open.ShowDialog()== DialogResult.OK)
{
PictureBox p = new PictureBox();
p.Image = new Bitmap(open.FileName); //OutOfMemory
TabPage t = new TabPage();
t.Text = open.FileName;
p.Parent = t;
p.Dock = DockStyle.Fill;
p.SizeMode = PictureBoxSizeMode.StretchImage;
tc_TP.TabPages.Add(t);
}
}
重复加载100-400K左右的图片,试了20+次,没问题。但加载1.2M的图片就报OutOfMemory了。查了查,可以参考下这个贴子。
{}感觉上 close(),Dispose的方法都没啥用每次出错我都用using
我用了你的方法还是不行,重复几次后就出错了,而且还没有什么规律。to:Going1981
我每加载完图片内存基本不变,但是出错的时候内存会涨很多。对了,我这也会有大图片,大图片你是如何处理的呀?
byte[] data = (byte[])dr["TP"];
if (data.Length > 0)
{
MemoryStream myStream = new MemoryStream();
foreach (byte a in data)
{
myStream.WriteByte(a);
}DataSet ds->byte[] data ->MemoryStream myStream
会不会是SqliteHelper的问题呢,都是直接地址引用来的
把SqliteHelper清理一下,静态变量清一下,或者换个读数据库的方法
我单步调试过,就是在System.Drawing.Bitmap bmp = new Bitmap(myStream);这一步出的错误。而且在PDA上直接选择一张大的图片(几兆)也会出错。
http://www.c-sharpcorner.com/Forums/Thread/56858/out-of-memory-exception-when-resizing-bitmap.aspxhttp://social.msdn.microsoft.com/forums/en-US/netfxcompact/thread/fccd0e3d-db6a-445b-b4f1-d21b508146dc/http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx
可查阅MSDN相关文档,有明确说明。所以在对内存有较大要求的系统中确实是个定时炸弹,以下方案,可能对你有帮助:
[我们唯一能做的是]
尽量少申请大内存,
尽量在每个页面退出时进行内存回收(如多用using),
尽量以牺牲性能来强制垃圾回收(有时变态到每个UI退出时就得调一次)。
这名修改成了using(MemoryStream myStream = new MemoryStream())而且在最后也加了GC.Collect();
但是问题还是出现,只不过好像出错的时候运行的次数多一些了。