Ich arbeite an einer Software in C# zum Bearbeiten von Bildern. Ich habe viele Bilder (mehr als 11.000), und wenn ich mein Programm nach wenigen Minuten ausführen, ich habe eine „OutOfMemoryException“Array in Schleife erstellen Raise eine OutOfMemoryException
Es ist mein Code:
private void GenerateImages()
{
try
{
Parallel.ForEach(listImagesStart, startImg =>
{
bool docontinue = true;
try
{
startImg.LoadImage(_baseFileResults);
}
catch
{
docontinue = false;
}
if (docontinue)
{
//Save image as file
startImg.Save();
// Do rotate
MyImg lastRotate = baseImg;
MyImg imgtmp;
String[] tabRotate = new String[3] { "_90", "_180", "_270"};
foreach (String rotate in tabRotate)
{
imgtmp = new GenImg(baseImg.FileName + rotate + baseImg.FileExtension);
imgtmp.LoadImage(lastRotate);
imgtmp.Rotate90();
imgtmp.Save();
lastRotate = imgtmp;
}
startImg.Dispose();
imgtmp.Dispose();
}
});
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
#if DEBUG
MessageBox.Show(e.StackTrace, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
#endif
}
}
Und MyImg:
class myImg
{
public Byte[] Matrix;
public int Height;
public int Width;
public void LoadImage(String filePath)
{
// create new Matrix/Heigth/Width from file
}
public void LoadImage(myImg img)
{
Matrix = new Byte[img.Matrix.Length];
Array.Copy(img.Matrix, Matrix, img.Matrix.Length);
Height = img.Height;
Width = img.Width;
}
public void Rotate90()
{
// Save before
int tmpWidth = Height;
int tmpHeight = Width;
Byte[] tmpMatrix = new Byte[Matrix.Length];
for (int r = 0; r < tmpHeight; r++)
{
for (int c = 0; c < tmpWidth; c++)
{
int prevR = Height - c - 1;
int prevC = r;
tmpMatrix[c + r * tmpWidth] = Matrix[prevC + prevR * Width];
}
}
// Copy new image
Array.Copy(tmpMatrix, Matrix, Matrix.Length);
Width = tmpWidth;
Height = tmpHeight;
}
public void Dispose()
{
SavePath = null;
Matrix = null;
Points = null;
Width = 0;
Height = 0;
GC.Collect();
}
}
Die SystemOutOfMemoryException tritt bei Anweisung new Byte[Length]
auf. Ich denke, ich erstelle zu viele Arrays, aber ich weiß nicht, was ich tun soll.
In Ihrem foreach-Schleife rufen Sie imgtmp.LoadImage sowie rotate90 beide alllocate den Speicher. Ist das die Schleife, wo Sie 11000 Bilder verarbeiten? Darüber hinaus erwähnen Sie nicht, wie groß jedes Bild ist. Sie rufen nicht auf, bis Sie diese Schleife verlassen. Und diese foreach-Schleife ist innerhalb einer Parallele für. Sie sollten überdenken, wie Sie Ihren Dispose aufrufen. –
@DaveS Ich bearbeite meine 11000 Bilder in 'Parallel.Foreach', die Liste ist' listImagesStart'. Bilder sind 700x700 Pixel. Ich habe meinen Code so geändert, dass er "Dispose" aufruft, wenn "docover" falsch ist. (Ich warte auf Ergebnisse) –