我希望尽可能少地使用RAM - 使用Windows窗体和Aforge.Net来捕获视频。 问题是,当我尝试例如"。Dispose()"我得到例外的一些元素:
static void Main()
{
Console.WriteLine("Main");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); <----- here VS showing me an exception (An unhandled exception of type 'System.InvalidOperationException' occurred in System.Drawing.dll)
}
执行此操作的代码:
public void setLocalCamera(string cameraName)
{
videoSource = new VideoCaptureDevice(cameraName);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
videoSource.Start();
}
Bitmap bitmap;
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (bitmap != null)
bitmap.Dispose(); <--- here is the problematic code
bitmap = (Bitmap)eventArgs.Frame.Clone();
pB_Camera.Image = bitmap;
}
此代码用于随机时间异常(我不知道究竟是什么火上浇油)。我也尝试了一些其他的解决方案,但我找不到任何工作/帮助(比如在pB_Camera.Image = bitmap之后make bitmap.Dispose();但这也是例外)
如何解决此问题并尽可能多地释放内存?
答案 0 :(得分:-1)
避免异常和闪烁的正确顺序是:
Bitmap bitmap;
void SetBitmap(Bitmap value)
{
pB_Camera.Image = value;
if (bitmap != null) bitmap.Dispose();
bitmap = value;
}
,用法很简单:
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
SetBitmap((Bitmap)eventArgs.Frame.Clone());
}
编辑:但是,您的具体情况略有不同,因为事件是在非UI线程上引发的。虽然简单的Control.Invoke
可以使用,但如果框架仅用于显示,我认为最好实现一个小的单项生产者/消费者&#34;非阻塞模式,为了让工作线程在您使用图像时继续处理,如下所示:
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
PushNextFrame((Bitmap)eventArgs.Frame.Clone());
}
Bitmap nextFrame;
void PushNextFrame(Bitmap value)
{
var prevFrame = Interlocked.Exchange(ref nextFrame, value);
if (prevFrame != null)
{
// previous frame has not been consumed, so just discard it.
// no need to notify the consumer, because it should have been done already.
prevFrame.Dispose();
}
else
{
// previos frame has been consumed and we just set a new one, so we need to notity the consumer.
BeginInvoke((Action)OnNextFrameAvailable);
}
}
Bitmap PullNextFrame() { return Interlocked.Exchange(ref nextFrame, null); }
void OnNextFrameAvailable()
{
DisplayFrame(PullNextFrame());
}
Bitmap currentFrame;
void DisplayFrame(Bitmap value)
{
pb_Camera.Image = value;
if (currentFrame != null) currentFrame.Dispose();
currentFrame = value;
}