我有一个TCP应用程序,我可以从客户端请求服务器上的文件夹中的图像。如果我要求一个小文件夹,它工作正常。如果它是一个大文件夹,它将抛出一个内存不足的异常。但是之后的任何事情,即使是一个带有1个文件的文件夹也会抛出相同的内存异常。
我认为它可能是内存不足的线程,所以我试图把它放在一个单独的线程和任务上,但都没有用。这是我正在使用的代码:
public static void Images(string path)
{
new Task(() =>
{
try
{
string root = lookupDirectoryPath("Application data");
string backupPath = root + @"\Apple Computer\MobileSync\";
string imagePath = backupPath + path;
if (Directory.Exists(imagePath))
{
String[] allfiles = Directory.GetFiles(imagePath, "*.*", SearchOption.AllDirectories);
List<Image> allImages = new List<Image>();
foreach (string file in allfiles)
{
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
}
}
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
serverSendByteArray(data, 12);
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("backup contained no images"), 1);
}
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("iphone backup folder does not exist"), 1);
}
}
catch (Exception ex)
{
if (ex.GetType().IsAssignableFrom(typeof(OutOfMemoryException)))
{
serverSendByteArray(Encoding.Default.GetBytes("Out of memory, could not send iphone images"), 1);
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("Unknown error, could not send iphone images"), 1);
}
}
}).Start();
}
在allImages.Add(Image.FromFile(file))中抛出异常;
这是isImage()函数:
public static bool IsImage(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
List<string> jpg = new List<string> { "FF", "D8" };
List<string> bmp = new List<string> { "42", "4D" };
List<string> gif = new List<string> { "47", "49", "46" };
List<string> png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
List<List<string>> imgTypes = new List<List<string>> { jpg, bmp, gif, png };
List<string> bytesIterated = new List<string>();
for (int i = 0; i < 8; i++)
{
string bit = stream.ReadByte().ToString("X2");
bytesIterated.Add(bit);
bool isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
if (isImage)
{
return true;
}
}
return false;
}
感谢您的帮助
答案 0 :(得分:0)
Image.FromFile似乎导致错误。在下面的问题中,它是一个corrupeted图像文件或用尽文件句柄,Image.FromStream()做得更好。值得一试,因为你已经打开了流:
答案 1 :(得分:0)
我试过,我可以重现你的问题。它绝对没有内存,没有像“它似乎只是”内存使用量增加到大约4 GB,然后出现错误。控制台输出只是为了看看那里发生了什么。
Image对象似乎不是保存数据的最佳方式。
我尝试了这个,并让它与许多文件一起使用。也许您可以更改代码以满足您的需求:
String[] allfiles = Directory.GetFiles(imagePath, "*.*", SearchOption.AllDirectories);
//List<Image> allImages = new List<Image>();
List<Byte[]> allImagesBytes = new List<Byte[]>();
foreach (string file in allfiles)
{
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
Console.Clear();
Console.Write(allImagesBytes.Count());
//allImages.Add(Image.FromStream(stream));
//allImages.Add(Image.FromFile(file));
allImagesBytes.Add(File.ReadAllBytes(file));
}
}
}
答案 2 :(得分:-1)
尝试更改此
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
}
...
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
serverSendByteArray(data, 12);
}
进入这个:
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
stream.Close();
}
....
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
foreach(Image img in allImages)
{
img.Dispose();
}
serverSendByteArray(data, 12);
}