代码之家  ›  专栏  ›  技术社区  ›  user7768436

C#使用“new bitmap()”的两个线程和笔记本电脑卡住

  •  -1
  • user7768436  · 技术社区  · 8 年前

    我的程序有两个线程,从两个摄像头抓取数据,每个线程将用于更新PictureBox:

        private void StartGrabLoop()
        {
            m_grabThread = new BackgroundWorker();
            m_grabThread.ProgressChanged += new ProgressChangedEventHandler(UpdateUI);
            m_grabThread.DoWork += new DoWorkEventHandler(GrabLoop);
            m_grabThread.WorkerReportsProgress = true;
            m_grabThread.RunWorkerAsync();
        }
    
    
        private void StartGrabLoop1()
        {
            m_grabThread1 = new BackgroundWorker();
            m_grabThread1.ProgressChanged += new ProgressChangedEventHandler(UpdateUI1);
            m_grabThread1.DoWork += new DoWorkEventHandler(GrabLoop1);
            m_grabThread1.WorkerReportsProgress = true;
            m_grabThread1.RunWorkerAsync();
        }
    
    
        private void GrabLoop(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
    
            while (m_grabImages)
            {
                try
                {
                    m_camera.RetrieveBuffer(m_rawImage);
                }
                catch (FC2Exception ex)
                {
                    Debug.WriteLine("Error: " + ex.Message);
                    continue;
                }
    
                lock (this)
                {
                    m_rawImage.Convert(PixelFormat.PixelFormatBgr, m_processedImage);
                }
    
                worker.ReportProgress(0);
            }
    
            m_grabThreadExited.Set();
        }
    
    
    
        private void GrabLoop1(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
    
            while (m_grabImages1)
            {
                try
                {
                    m_camera1.RetrieveBuffer(m_rawImage1);
                }
                catch (FC2Exception ex)
                {
                    Debug.WriteLine("Error: " + ex.Message);
                    continue;
                }
    
                lock (this)
                {
                    m_rawImage1.Convert(PixelFormat.PixelFormatBgr, m_processedImage1);
                }
    
                worker.ReportProgress(0);
            }
    
            m_grabThreadExited1.Set();
        }
    
     private void UpdateUI(object sender, ProgressChangedEventArgs e)
            {
                Bitmap source = m_processedImage.bitmap;
                Bitmap resized = new Bitmap(source, source.Width / zoom, source.Height / zoom);
                pictureBox1.Image = resized;
                pictureBox1.Invalidate();
    }
     private void UpdateUI1(object sender, ProgressChangedEventArgs e)
            {
                Bitmap source = m_processedImage.bitmap;
                Bitmap resized = new Bitmap(source, source.Width / zoom, source.Height / zoom);
                pictureBox2.Image = resized;
                pictureBox2.Invalidate();
    }
    

    关键是它可以在我的桌面上运行得很好。但我的笔记本电脑内存有问题,要么显示白色图像,要么忙着崩溃。我做了很多研究,并尝试了dispose(),或System。总承包商。Collect();系统总承包商。WaitForPendingFinalizers();他们都不管用,有人能帮我吗?我之所以使用“新位图”,是因为我想简化缩放功能。。。。

    1 回复  |  直到 8 年前
        1
  •  0
  •   Nyerguds    8 年前

    制作新图像时最好不要与旧图像有任何链接;它可以帮助垃圾收集更好地运行。此外,在放入新版本时,还要显式地处理旧版本。

    private void UpdateUI(object sender, ProgressChangedEventArgs e)
    {
        Bitmap source = m_processedImage.bitmap;
        Bitmap resized = CreateWithNewSize(source, source.Width / zoom, source.Height / zoom);
        // Save reference to old image in the control
        Image oldImg = pictureBox1.Image;
        pictureBox1.Image = resized;
        // specifically dispose old image to avoid memory usage buildup
        if (oldImg != null)
        {
            try{ oldImg.Dispose(); }
            catch { /* Ignore; won't help much to process this */ }
        }
        // Request refresh.
        pictureBox1.Invalidate();
    }
    

    ...并对pictureBox2执行相同的操作。如所述 中间 不过,您可能需要在工作线程和UI线程之间设置正确的通信,可能需要使用委托。在这种情况下,我的 Save reference to old image 注释可能应该放在名为函数的委托中,以替换UI控件上的图像。

    调整大小的方法非常简单:

    public static Bitmap CreateWithNewSize(Image image, Int32 newWidth, Int32 newHeight)
    {
        Bitmap bp = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppArgb);
        using (Graphics gr = Graphics.FromImage(bp))
            gr.DrawImage(image, new Rectangle(0, 0, newWidth, newHeight));
        return bp;
    }
    

    可能应该调用相同的图像处理代码 m_processedImage1 在更换之前 m_rawImage1.Convert 呼叫由于这段新代码将为您的UI创建干净的未链接副本,因此这种处理也不会导致任何问题。