C# WriteableBitmap上发生OutOfMemoryException
我正在开发一个windows phone应用程序,用于将图像上载到web服务器。我正在将设备中的所有图像选择到一个列表对象中。我正在将所有位图图像逐个转换为字节[] 我的代码C# WriteableBitmap上发生OutOfMemoryException,c#,windows-phone-7,windows-phone-8,bitmapimage,C#,Windows Phone 7,Windows Phone 8,Bitmapimage,我正在开发一个windows phone应用程序,用于将图像上载到web服务器。我正在将设备中的所有图像选择到一个列表对象中。我正在将所有位图图像逐个转换为字节[] 我的代码 public byte[] ConvertToBytes(BitmapImage bitmapImage) { byte[] data = null; WriteableBitmap wBitmap = null; using (MemoryStream strea
public byte[] ConvertToBytes(BitmapImage bitmapImage)
{
byte[] data = null;
WriteableBitmap wBitmap = null;
using (MemoryStream stream = new MemoryStream())
{
wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
//data = stream.GetBuffer();
data = stream.ToArray();
DisposeImage(bitmapImage);
return data;
}
}
public void DisposeImage(BitmapImage image)
{
if (image != null)
{
try
{
using (MemoryStream ms = new MemoryStream(new byte[] { 0x0 }))
{
image.SetSource(ms);
}
}
catch (Exception ex)
{
}
}
}
从位图到字节的转换
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("ImagesZipFolder"))
{
//MediaImage mediaImage = new MediaImage();
//mediaImage.ImageFile = decodeImage(new byte[imgStream[0].Length]);
//lstImages.Items.Add(mediaImage);
store.CreateDirectory("ImagesZipFolder");
for (int i = 0; i < imgname.Count(); i++)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\" + imgname[i], FileMode.CreateNew,store))
//using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\text.txt" , System.IO.FileMode.OpenOrCreate, store))
{
// byte[] bytes = new byte[imgStream[i].Length];
byte[] bytes = ConvertToBytes(ImgCollection[i]);
stream.Write(bytes, 0, bytes.Length);
}
}
}
else {
directory = true;
}
}
使用(IsolatedStorageFile store=IsolatedStorageFile.GetUserStoreForApplication())
{
如果(!store.DirectoryExists(“ImagesZipFolder”))
{
//MediaImage MediaImage=新的MediaImage();
//mediaImage.ImageFile=decodeImage(新字节[imgStream[0].Length]);
//lstmages.Items.Add(mediaImage);
store.CreateDirectory(“ImagesZipFolder”);
for(int i=0;i
我的模拟器中有91个图像。当我将所有这些位图图像转换为字节[]时,get在第wBitmap=new WriteableBitmap(位图图像)行出现以下错误代码>
System.Windows.ni.dll中发生“System.OutOfMemoryException”类型的异常,但未在用户代码中处理
如何解决此错误
网络服务
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("ImagesZipFolder"))
{
//MediaImage mediaImage = new MediaImage();
//mediaImage.ImageFile = decodeImage(new byte[imgStream[0].Length]);
//lstImages.Items.Add(mediaImage);
store.CreateDirectory("ImagesZipFolder");
for (int i = 0; i < imgname.Count(); i++)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\" + imgname[i], FileMode.CreateNew,store))
//using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\text.txt" , System.IO.FileMode.OpenOrCreate, store))
{
// byte[] bytes = new byte[imgStream[i].Length];
byte[] bytes = ConvertToBytes(ImgCollection[i]);
stream.Write(bytes, 0, bytes.Length);
}
}
}
else {
directory = true;
}
}
若我们将巨大的文件发送到web服务,它是否会给出类似这样的错误
System.ServiceModel.ni.dll中发生“System.OutOfMemoryException”类型的异常,但未在用户代码中处理
如何解决此错误
改变你做事的方式,使用更少的内存
例如,不是转换每张图片然后上传它们,而是转换一张图片,上传它,转换下一张,依此类推
如果您真的想一次处理所有图片,您可以将字节数组存储在独立的存储器中,而不是将它们保存在内存中,并在需要时将它们读回
基本上,重新考虑您的过程,并在给定时间使用存储来减少内存使用
或者要求Microsoft取消Windows Phone上的内存限制,但这可能有点棘手。问题在于GC和位图图像如何协同工作,如本错误报告所述:
从报告中可以看出:
Silverlight加载图像时,框架会保留一个引用和
缓存解码图像,直到流控制返回到UI
线程调度程序。当你像那样在一个紧密的循环中加载图像时,
即使应用程序没有保留引用,GC也不能
释放图像,直到在启用流控制时释放引用
返回
在处理20个左右的图像后,您可以停止并排队等待下一个图像
设置使用Dispatcher.BeginInvoke只是为了中断正在进行的工作
一批处理。这将使我们能够释放不存在的图像
由您的应用程序保留
我理解目前的解码行为并不明显
Silverlight保留了这些引用,但更改了解码器
设计可能会影响其他领域,所以现在我建议进行处理
像这样的图片是成批的
现在,如果你真的想加载500张图片并保留它们,你可以
根据图像大小,仍有可能耗尽内存。如果
您处理的是一个多页文档,您可能希望改为
在后台按需加载页面,并在退出时释放
使用几页缓冲区进行查看,这样在任何时候都不会超过
合理的纹理内存限制
修复:
private List<BitmapImage> Images = .....;
private List<BitmapImage>.Enumerator iterator;
private List<byte[]> bytesData = new List<byte[]>();
public void ProcessImages()
{
if(iterator == null)
iterator = Images.GetEnumerator();
if(iterator.MoveNext())
{
bytesData.Add(ConvertToBytes(iterator.Current));
//load next images
Dispatcher.BeginInvoke(() => ProcessImages());
}else{
//all images done
}
}
public static byte[] ConvertToBytes(BitmapImage bitmapImage)
{
using (MemoryStream stream = new MemoryStream())
{
var wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}
}
私有列表图像=。。。。。;
私有列表。枚举器迭代器;
私有列表bytesData=新列表();
public void ProcessImages()
{
if(迭代器==null)
迭代器=Images.GetEnumerator();
if(iterator.MoveNext())
{
Add(ConvertToBytes(iterator.Current));
//加载下一个图像
Dispatcher.BeginInvoke(()=>ProcessImages());
}否则{
//所有图像完成
}
}
公共静态字节[]转换字节(位图图像位图图像)
{
使用(MemoryStream stream=new MemoryStream())
{
var wBitmap=新的可写bitmap(位图图像);
SaveJpeg(stream,wBitmap.PixelWidth,wBitmap.PixelHeight,0100);
stream.Seek(0,SeekOrigin.Begin);
返回流ToArray();
}
}
我找到了将位图图像转换为字节[]数组的新方法。不需要在内存中写入图像。
兔子是密码
public byte[] GetBytes(BitmapImage bi)
{
WriteableBitmap wbm = new WriteableBitmap(bi);
return ToByteArray(wbm);
}
public byte[] ToByteArray(WriteableBitmap bmp)
{
// Init buffer
int w = bmp.PixelWidth;
int h = bmp.PixelHeight;
int[] p = bmp.Pixels;
int len = p.Length;
byte[] result = new byte[4 * w * h];
// Copy pixels to buffer
for (int i = 0, j = 0; i < len; i++, j += 4)
{
int color = p[i];
result[j + 0] = (byte)(color >> 24); // A
result[j + 1] = (byte)(color >> 16); // R
result[j + 2] = (byte)(color >> 8); // G
result[j + 3] = (byte)(color); // B
}
return result;
}
public byte[]GetBytes(BitmapImage bi)
{
WriteableBitmap wbm=新的WriteableBitmap(bi);
返回到字节数组(wbm);
}
公共字节[]ToByteArray(WriteableBitmap bmp)
{
//初始化缓冲区
int w=bmp.PixelWidth;
int h=bmp.PixelHeight;
int[]p=bmp.像素;
int len=p.长度;
字节[]结果=新字节[4*w*h];
//将像素复制到缓冲区
对于(int i=0,j=0;i>24);//A
结果[j+1]=(字节)(颜色>>16);//R
结果[j+2]=(字节)(颜色>>8);//G
结果[j+3]=(字节)(颜色);//B
}
返回结果;
}
是否需要同时在内存中存储所有字节数组?