首页 > 解决方案 > Application.Run 试图读取或写入受保护的内存

问题描述

堆栈跟踪的详细信息

简而言之,我的应用程序是一个 Windows 窗体,它具有图片框来显示来自使用 ROI(感兴趣区域)检测手机屏幕的摄像头的实时馈送。

下面是例外

 -$exception {System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
 at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI(HandleRef graphics, HandleRef image, Int32 x, Int32 y, Int32 width, Int32 height)
 at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
 at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
 at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
 at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
 at System.Windows.Forms.Control.WmPaint(Message& m)
 at System.Windows.Forms.Control.WndProc(Message& m)
 at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)} System.AccessViolationException

下面是堆栈跟踪

    StackTrace  "at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI(HandleRef graphics, HandleRef image, Int32 x, Int32 y, Int32 width, Int32 height)\r\n   at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)\r\n   
    at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)\r\n   at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)\r\n   
    at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)\r\n   
    at System.Windows.Forms.Control.WmPaint(Message& m)\r\n   
    at System.Windows.Forms.Control.WndProc(Message& m)\r\n    
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)"  string

如果我让我的应用程序在以下行运行,Application.Run(MMI.MainMDI); 将尝试写入或读取受保护的内存;像下面

   static void Init()
    {
        MMI.Data = new CommonDataType();

        MMI.MainMDI = new MDIMain();
        MMI.MainMDI.Show();

        MMI.FrmMain = new FormMain();

        MMI.MainMDI.Text = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

        MMI.FrmMain.MdiParent = MMI.MainMDI;
        
        MMI.FrmMain.StartPosition = FormStartPosition.Manual;
        MMI.FrmMain.Location = new System.Drawing.Point(MMI.MainMDI.ClientRectangle.Location.X, MMI.MainMDI.ClientRectangle.Y);
        MMI.FrmMain.Width = MMI.MainMDI.ClientRectangle.Size.Width - 10;

        MMI.FrmMain.Show();
       
        GenericMachine.SetMessageLogForm(MMI.FrmMsg);

        if (!MMI.Data.Config.LoadConfig())
        {
            MessageBox.Show("Error Loading Config File Data... Application Will Be Closed");
            Environment.Exit(0);
        }

        MMI.DBCtrl = new MainDBControl();
        MMI.DBCtrl.Start();

        MMI.DevCtrl = new MainDevControl();
        MMI.DevCtrl.Start();

        MMI.IOCtrl = new MainIOControl();
        MMI.IOCtrl.Start();

        MMI.CycleCtrl = new MainCycleControl();
        MMI.CycleCtrl.Start();
    }

    static void DeInit()
    {
        if (MMI.IOCtrl != null) MMI.IOCtrl.Dispose();
        if (MMI.DevCtrl != null) MMI.DevCtrl.Dispose();
        if (MMI.DBCtrl != null) MMI.DBCtrl.Dispose();
        if (MMI.CycleCtrl != null) MMI.CycleCtrl.Dispose();
        EndTask("loadmultipleimages.exe");
        EndTask("EXCEL.EXE");
    }

   static System.Threading.Mutex mutex = new System.Threading.Mutex(true, "Sensata MMI Application");

    [STAThread]
    static void Main()
    {
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Init();
            Application.Run(MMI.MainMDI);
            DeInit();
            mutex.ReleaseMutex();
        }
        else
        {
            MessageBox.Show("Application Already Running - Only One Instance is Allowed at One Time");
        }
    }

当我检查堆栈跟踪时,源来自 System.Drawing,我怀疑它来自我的 FORM 类。我认为这是因为即使没有检测到手机屏幕,图片框也会继续运行。因此,基本上我的 formshown 方法将始终刷新并触发事件处理程序 refreshscreen1 方法,因为 bool m_camerachoosen 始终为 true 以确保相机始终显示在 picturebox.Image 上,它会不断循环进入DetectText 函数。有没有办法解决这个尝试读取或写入受保护的内存?我已经面临这个问题将近 1 个月了。

    private void FormMain_Shown(object sender, EventArgs e)
    {
        if (m_screenRefreshTimer1 == null)
        {
            m_screenRefreshTimer1 = new System.Windows.Forms.Timer();
            m_screenRefreshTimer1.Interval = 200;
            m_screenRefreshTimer1.Tick += new System.EventHandler(refreshScreen1);
            m_screenRefreshTimer1.Start();
        }

        if (m_screenRefreshTimer2 == null)
        {
            m_screenRefreshTimer2 = new System.Windows.Forms.Timer();
            m_screenRefreshTimer2.Interval = 1000;
            m_screenRefreshTimer2.Tick += new System.EventHandler(refreshScreen2);
            m_screenRefreshTimer2.Start();
        }
    }

    private void refreshScreen1(object sender, EventArgs e)
    {
        if (MMI.CycleCtrl == null) return;

        m_screenRefreshTimer1.Stop();
        txtBoxRisk.Text = "";
        txtBoxDateTime.Text = "";
        txtBoxMYS.Text = "";
        txtboxhint.Text = MMI.Data.Mach.Hint;
        txtboxMSG.Text = MMI.Data.Mach.DBMessage;

        if (m_Camerachosen)
        {
            txtboxhint.BackColor = System.Drawing.Color.Aqua;
            //md.Hint = "PLEASE PLACE YOUR PHONE AT THE DESIGNATED AREA";
            DetectText(myImage);
        }
    }

   private void refreshScreen2(object sender, EventArgs e)
   {
      m_screenRefreshTimer2.Stop();
      m_screenRefreshTimer2.Start();
   }

    private void startToolStripMenuItem_Click(object sender, EventArgs e)
    {
        VideoCaptureDevice = new VideoCaptureDevice(filterInfoCollection[comboBox1.SelectedIndex].MonikerString);
        VideoCaptureDevice.NewFrame += VideoCaptureDevice_NewFrame;
        VideoCaptureDevice.Start();
    }

    private void VideoCaptureDevice_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        Bitmap picboxclone = (Bitmap)eventArgs.Frame.Clone();
        myImage = new Image<Bgr, Byte>(picboxclone);
        m_Camerachosen = true;
    }

    private void DetectText(Image<Bgr, byte> img)
    {
        Image<Bgr, byte> imgclone = img;
        Image<Gray, byte> sobel = img.Convert<Gray, byte>().Sobel(1, 0, 3).AbsDiff(new Gray(0.0)).Convert<Gray, byte>().ThresholdBinary(new Gray(90), new Gray(255));
        var mask = img.Convert<Gray, byte>().SmoothMedian(3).
                    ThresholdBinary(new Gray(150), new Gray(255));

        Mat SE = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Rectangle, new Size(1, 1), new Point(-1, -1));
        sobel = sobel.MorphologyEx(Emgu.CV.CvEnum.MorphOp.Dilate, SE, new Point(-1, -1), 1, Emgu.CV.CvEnum.BorderType.Reflect, new MCvScalar(255));


        Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
        Emgu.CV.Util.VectorOfVectorOfPoint contours2 = new Emgu.CV.Util.VectorOfVectorOfPoint();

        Mat m = new Mat();

        CvInvoke.FindContours(sobel, contours, m, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
        CvInvoke.FindContours(mask, contours2, m, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);

        List<Rectangle> list = new List<Rectangle>();
        Rectangle maskrect = new Rectangle();
   }

标签: c#winformsemgucv

解决方案


推荐阅读