Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用进程时内存不足_C#_Process_Imagemagick Convert - Fatal编程技术网

C# 使用进程时内存不足

C# 使用进程时内存不足,c#,process,imagemagick-convert,C#,Process,Imagemagick Convert,好的,所以我知道我应该使用ImageMagick DLL。。。我正在学习,测试,并努力做到这一点。但与此同时,我正在使用一种低效的方法,通过进程调用Imagemagick的convert.exe 当我测试时,它可以很好地处理数百个图像。但后来我把WindowsForms程序移到一台速度更快的机器上,它每次都会在同一点崩溃 这是一个两步流程调用。第一次遍历所有文件并生成PNG。然后我循环遍历所有PNG并将其与背景合成并输出JPG。但每次恰好有22张图像时,它都会出错“System.OutOfMem

好的,所以我知道我应该使用ImageMagick DLL。。。我正在学习,测试,并努力做到这一点。但与此同时,我正在使用一种低效的方法,通过进程调用Imagemagick的convert.exe

当我测试时,它可以很好地处理数百个图像。但后来我把WindowsForms程序移到一台速度更快的机器上,它每次都会在同一点崩溃

这是一个两步流程调用。第一次遍历所有文件并生成PNG。然后我循环遍历所有PNG并将其与背景合成并输出JPG。但每次恰好有22张图像时,它都会出错“System.OutOfMemoryException:Out memory:Out memory.”有什么东西填满了,我需要杀死还是什么

    foreach (string file in files)
            {
                try
                {
                    string captureImg = Path.GetFileName(file);
                    string maskImg = file.Replace("X.JPG", "Y.JPG");
                    string OutputImage = string.Format("{0}.png", Path.GetFileNameWithoutExtension(captureImg));
                    string output = Path.Combine(destFolder, OutputImage);
                    //MessageBox.Show(output);
                    progressBarImage.Value = progressBarImage.Value + 1;
                    lblStatus.Text = string.Format("Image {0} of {1}", progressBarImage.Value, maxFiles);
                    makePNG(file, maskImg, output);
                    Application.DoEvents();

                }
                catch (Exception)
                {
                }
            }

            if (chkBG.Checked)
            {
                //try
                //{
                    string JPGdir = Path.Combine(destFolder, "JPGs");
                    string[] PNGfiles = Directory.GetFiles(destFolder, "*C.PNG");

                    lblProgress.Text = "Generating JPGs with Background";
                    progressBarImage.Value = 0;
                    progressBarImage.Maximum = files.Length;
                    message = "PNG and JPG Export Complete";
                    if (!Directory.Exists(JPGdir))
                    {
                        Directory.CreateDirectory(JPGdir);
                    }
                    foreach (string PNGfile in PNGfiles)
                    {
                        Application.DoEvents();
                        string outputJPG = string.Format("{0}.jpg", Path.GetFileNameWithoutExtension(PNGfile));
                        string result = Path.Combine(JPGdir, outputJPG);
                        progressBarImage.Value += 1;
                        lblStatus.Text = string.Format("Image {0} of {1}", progressBarImage.Value, files.Length);
                        makeJPG(PNGfile, txtBackground.Text, result);
                        //MessageBox.Show(PNGfile);

                    }

private void makePNG(string source, string mask, string output)
        {
            if (!source.EndsWith("Y.JPG"))
            {
                Process proc = new Process();
                string appPath = Path.GetDirectoryName(Application.ExecutablePath);
                proc.EnableRaisingEvents = false;
                proc.StartInfo.FileName = @"""C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe""";
                proc.StartInfo.Arguments = string.Format(@"{0} {1} -alpha off -compose  copy-opacity -level 5%  -composite {2}", source, mask, output);
                proc.StartInfo.UseShellExecute = false;
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.WaitForExit();

            }
        }

        private void makeJPG(string source, string background, string output)
        {
            float BGimg = Image.FromFile(background).Height;
            float SubjectImg = Image.FromFile(source).Height;
            float ResultHeight = 100 * (BGimg / SubjectImg);
            int Height = Convert.ToInt32(ResultHeight);


            Process procJPG = new Process();
            string appPath = Path.GetDirectoryName(Application.ExecutablePath);
            procJPG.EnableRaisingEvents = false;
            procJPG.StartInfo.FileName = @"""C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe""";
            procJPG.StartInfo.Arguments = string.Format(@"{1} ( {0} -resize {3}% ) -gravity South -composite {2}", source, background, output, Height);
            procJPG.StartInfo.UseShellExecute = false;
            procJPG.StartInfo.RedirectStandardOutput = true;
            procJPG.StartInfo.CreateNoWindow = true;
            procJPG.Start();
            procJPG.WaitForExit();
        }

乍一看,您在
makeJPG()
中使用了两次
Image.FromFile
,而没有处理对象
Image.FromFile
通常会创建需要释放的非托管GDI+句柄

从:

在释放图像之前,文件将保持锁定状态

因此,乍一看,我认为您只是在内存中加载了太多图像,我会尝试:

private void makeJPG(string source, string background, string output)
{
  using(var backgroundImg = Image.FromFile(background))
  using(var sourceImg = Image.FromFile(source))
  {
    float BGimg = backgroundImg.Height;
    float SubjectImg = sourceImg.Height;
    float ResultHeight = 100 * (BGimg / SubjectImg);
    int Height = Convert.ToInt32(ResultHeight);


    Process procJPG = new Process();
    string appPath = Path.GetDirectoryName(Application.ExecutablePath);
    procJPG.EnableRaisingEvents = false;
    procJPG.StartInfo.FileName = @"""C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe""";
    procJPG.StartInfo.Arguments = string.Format(@"{1} ( {0} -resize {3}% ) -gravity South -composite {2}", source, background, output, Height);
    procJPG.StartInfo.UseShellExecute = false;
    procJPG.StartInfo.RedirectStandardOutput = true;
    procJPG.StartInfo.CreateNoWindow = true;
    procJPG.Start();
    procJPG.WaitForExit();
  }
}
由于您实际上没有使用图像(只是获取它们的高度),您可以使用块将这些
块变小,但我将留给您

。。。但是

关于OutOfMemoryException 另外,您说它正好发生在22个图像上(这对于内存不足来说是很奇怪的,除非图像总是很大),但是阅读相同的文档:

如果文件没有有效的图像格式,或者GDI+不支持文件的像素格式,此方法将抛出OutOfMemoryException异常


因此,请确保第22幅图像(无论是“源”还是“背景”,取决于它抛出的位置)的格式正确

乍一看,您在
makeJPG()
中使用了
image.FromFile
两次,而没有处理对象
Image.FromFile
通常会创建需要释放的非托管GDI+句柄

从:

在释放图像之前,文件将保持锁定状态

因此,乍一看,我认为您只是在内存中加载了太多图像,我会尝试:

private void makeJPG(string source, string background, string output)
{
  using(var backgroundImg = Image.FromFile(background))
  using(var sourceImg = Image.FromFile(source))
  {
    float BGimg = backgroundImg.Height;
    float SubjectImg = sourceImg.Height;
    float ResultHeight = 100 * (BGimg / SubjectImg);
    int Height = Convert.ToInt32(ResultHeight);


    Process procJPG = new Process();
    string appPath = Path.GetDirectoryName(Application.ExecutablePath);
    procJPG.EnableRaisingEvents = false;
    procJPG.StartInfo.FileName = @"""C:\Program Files\ImageMagick-6.9.0-Q16\convert.exe""";
    procJPG.StartInfo.Arguments = string.Format(@"{1} ( {0} -resize {3}% ) -gravity South -composite {2}", source, background, output, Height);
    procJPG.StartInfo.UseShellExecute = false;
    procJPG.StartInfo.RedirectStandardOutput = true;
    procJPG.StartInfo.CreateNoWindow = true;
    procJPG.Start();
    procJPG.WaitForExit();
  }
}
由于您实际上没有使用图像(只是获取它们的高度),您可以使用
块将这些
块变小,但我将留给您

。。。但是

关于OutOfMemoryException 另外,您说它正好发生在22个图像上(这对于内存不足来说是很奇怪的,除非图像总是很大),但是阅读相同的文档:

如果文件没有有效的图像格式,或者GDI+不支持文件的像素格式,此方法将抛出OutOfMemoryException异常


因此,请确保第22幅图像(无论是“源”还是“背景”,取决于它抛出的位置)具有正确的格式

为什么要重定向standard out?
Application.DoEvents()尽量不要使用该。。这不好practice@MethodMan我不同意
Application.DoEvents()
如果使用得当的话是非常好的(但是正确使用它是很难的;-)@Jcl happy reading..@MethodMan我读过很多关于它的书(包括那些说“它很邪恶而且从不使用它”的书),但是在我多年从事Windows.Forms的工作中,我已经在很多场合成功地使用了它,特别是在直接处理消息队列以处理WinForms中不存在的复杂功能时。它基本上等同于直接在Win32 C++中使用的旧代码> PekMeime/Cuth.Road,如果你理解使用它的含义,那么就没有什么错了。是“DoEvents()的糟糕用法”让它变得邪恶,而不是每个sew的函数。你为什么要将标准重定向出去?
Application.DoEvents()尽量不要使用该。。这不好practice@MethodMan我不同意
Application.DoEvents()
如果使用得当的话是非常好的(但是正确使用它是很难的;-)@Jcl happy reading..@MethodMan我读过很多关于它的书(包括那些说“它很邪恶而且从不使用它”的书),但是在我多年从事Windows.Forms的工作中,我已经在很多场合成功地使用了它,特别是在直接处理消息队列以处理WinForms中不存在的复杂功能时。它基本上等同于直接在Win32 C++中使用的旧代码> PekMeime/Cuth.Road,如果你理解使用它的含义,那么就没有什么错了。是“DoEvents()的错误用法”让它变得邪恶,而不是每个seavesome的函数。。。就这样。只是读得太多而没有正确处理。非常感谢。令人惊叹的。。。就这样。只是读得太多而没有正确处理。非常感谢。