我的程序有两个线程,从两个摄像头抓取数据,每个线程将用于更新一个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.GC.Collect((; System.GC.WaitForPendingFinalizers((;它们都不起作用,有人可以帮助我吗?我使用"新位图"的原因是因为我想简单的缩放功能......
制作新图像而不链接到旧图像总是更好的;它有助于垃圾回收更好地运行。此外,在放入新版本时显式释放旧版本。
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 执行相同的操作。但是,如 InBetween 所述,您可能需要在工作线程和 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_rawImage1.Convert
调用中,在替换它之前,可能应该在m_processedImage1
调用相同的图像释放代码。由于此新代码将为您的 UI 制作干净的未链接副本,因此此释放也不会造成任何问题。