0

问题是有时我的程序会占用大量内存并崩溃。相反,当用户达到内存限制或内存限制达到 100% 时,我需要以某种方式提醒或告诉用户,除了崩溃之外,还需要执行其他操作。

我正在使用占用大量内存的 ffmpeg.exe。

private void beginOperationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            svrNotifyIcon.Icon = Properties.Resources.Icons_Land_Play_Stop_Pause_Record_Normal;
            changeFileNameToolStripMenuItem.Enabled = false;
            beginOperationToolStripMenuItem.Enabled = false;
            if (File.Exists(fullDefaultDirectory))
            {
                File.Delete(fullDefaultDirectory);
            }
            ffmp.Start(fullDefaultDirectory, 25);//"test.avi", @"d:\", 25);
            timer1.Enabled = true;
            startStop = true;
        }

ffmp.Start 在我的新课程中:

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using DannyGeneral;

namespace ScreenVideoRecorder
{
    class Ffmpeg
    {
        NamedPipeServerStream p;
        String pipename = "mytestpipe";
        byte[] b;
        System.Diagnostics.Process process;
        string ffmpegFileName = "ffmpeg.exe";
        string workingDirectory;

        public Ffmpeg()
        {
            workingDirectory = Path.GetDirectoryName(Application.ExecutablePath);//System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);//Application.StartupPath; //Path.GetDirectoryName(Application.ExecutablePath);// +@"\workingDirectory";
            Logger.Write("workingDirectory: " + workingDirectory);
            if (!Directory.Exists(workingDirectory))
            {
                Directory.CreateDirectory(workingDirectory);
            }
            ffmpegFileName = Path.Combine(workingDirectory, ffmpegFileName);//@"\ffmpeg.exe";
            Logger.Write("FfmpegFilename: " + ffmpegFileName);
        }

        public void Start(string pathFileName, int BitmapRate)
        {
            try
            {
                string outPath = pathFileName;
                Logger.Write("Output Video File Directory: " + outPath);
                Logger.Write("Frame Rate: " + BitmapRate.ToString());
                p = new NamedPipeServerStream(pipename, PipeDirection.Out, 1, PipeTransmissionMode.Byte);
                b = new byte[1920 * 1080 * 3]; // some buffer for the r g and b of pixels of an image of size 720p

                ProcessStartInfo psi = new ProcessStartInfo();
                psi.WindowStyle = ProcessWindowStyle.Hidden;
                psi.UseShellExecute = false;
                psi.CreateNoWindow = true;
                psi.FileName = ffmpegFileName;
                Logger.Write("psi.FileName: " + psi.FileName);
                psi.WorkingDirectory = workingDirectory;
                Logger.Write("psi.WorkingDirectory: " + psi.WorkingDirectory);
                psi.Arguments = @"-f rawvideo -pix_fmt bgr0 -video_size 1920x1080 -i \\.\pipe\mytestpipe -map 0 -c:v libx264 -r " + BitmapRate + " " + outPath;
                Logger.Write("ProcessStartInfo Arguments" + @"-f rawvideo -pix_fmt bgr0 -video_size 1920x1080 -i \\.\pipe\mytestpipe -map 0 -c:v libx264 -r " + BitmapRate + " " + outPath);
                //psi.RedirectStandardOutput = true;
                process = Process.Start(psi);
                process.EnableRaisingEvents = false;
                p.WaitForConnection();
            }
            catch (Exception err)
            {
                Logger.Write("Exception Error: " + err.ToString());
            }
        }

        public void PushFrame(Bitmap bmp)
        {
            try
            {
                int length;
                // Lock the bitmap's bits.
                //bmp = new Bitmap(1920, 1080);
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                //Rectangle rect = new Rectangle(0, 0, 1280, 720);
                System.Drawing.Imaging.BitmapData bmpData =
                    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
                    bmp.PixelFormat);

                int absStride = Math.Abs(bmpData.Stride);
                // Get the address of the first line.
                IntPtr ptr = bmpData.Scan0;

                // Declare an array to hold the bytes of the bitmap.
                //length = 3 * bmp.Width * bmp.Height;
                length = absStride * bmpData.Height;
                byte[] rgbValues = new byte[length];

                //Marshal.Copy(ptr, rgbValues, 0, length);
                int j = bmp.Height - 1;
                for (int i = 0; i < bmp.Height; i++)
                {
                    IntPtr pointer = new IntPtr(bmpData.Scan0.ToInt32() + (bmpData.Stride * j));
                    System.Runtime.InteropServices.Marshal.Copy(pointer, rgbValues, absStride * (bmp.Height - i - 1), absStride);
                    j--;
                }
                p.Write(rgbValues, 0, length);
                bmp.UnlockBits(bmpData);
            }
            catch(Exception err)
            {
                Logger.Write("Error: " + err.ToString());
            }

问题是在内存中每 40 毫秒向管道发送一次位图会占用大量内存或 CPU。

所以我想向用户发送一条消息,他达到极限,然后停止程序或其他东西,只是为了不让它崩溃。

4

1 回答 1

0

这种事情很难有效地完成。

但是,您可能有一些运气,GC.RegisterForFullGCNotification()至少可以让您的代码知道何时接近完整的 GC。

有关更多详细信息,请参阅本文档:http: //msdn.microsoft.com/en-us/library/cc713687.aspx

但是我必须指出,这种事情很少能很好地发挥作用。

于 2013-06-10T12:49:12.537 回答