**关于可能的重复 - BackgroundWorker方法不适用于此。
以下是我尝试使用AForge库从IP摄像机接收视频。
每个视频流应该在单独的线程中运行,在新帧到达时通知UI线程。事件处理程序在同一个线程中执行,引发它,所以我需要使用Invoke。
所有操作都顺利进行,直到我想停止申请。标有'>>>'的行抛出ObjectDisposed异常,因此我的应用程序不会像运行一样顺利结束。
我知道问题是理解多线程,因为它无法看到真正的问题。有人可以解释一下这里发生了什么吗?
Form1.cs
public void generic_NewFrame(object sender, NewFrameEventArgs e)
{
...
if (pictureBox1.InvokeRequired)
{
>>> pictureBox1.Invoke(new MethodInvoker(delegate()
{
pictureBox1.BackgroundImage = (Image)buf;
}));
}
else
{
pictureBox1.BackgroundImage = (Image)buf;
}
...
}
尽可能短,Camera class:
Camera.cs
//Camera thread loop
private void WorkerThread()
{
while (!stopEvent.WaitOne(0, false))
{
...
if (!stopEvent.WaitOne(0, false))
{
// notify UI thread
OnNewFrame(new NewFrameEventArgs(Last_frame));
...
}
}
override public void Play()
{
stopEvent = new ManualResetEvent(false);
thread = new Thread(new ThreadStart(WorkerThread));
thread.Start();
}
override public void Stop()
{
if (thread != null)
{
stopEvent.Set();
}
}
答案 0 :(得分:1)
我认为问题出在以下方面:图书馆在关闭您的表单后调用您的回调(generic_NewFrame
)。
你可以用几种不同的方式解决它。
首先,如果您的表单已经处理,您可以跳过回调方法:
public void generic_NewFrame(object sender, NewFrameEventArgs e)
{
// Lets skip this callback if our form already closed
**if (this.IsDisposed) return;**
...
if (pictureBox1.InvokeRequired)
{
>>> pictureBox1.Invoke(new MethodInvoker(delegate()
{
pictureBox1.BackgroundImage = (Image)buf;
}));
}
else
{
pictureBox1.BackgroundImage = (Image)buf;
}
...
}
另一种方法是等待,不要关闭你的表格直到你的图书馆仍在工作并等待FormClosing
或FormClosed
事件处理程序:
private void FormClosingEventHandler(object sender, CancelEventArgs e)
{
// Waiting till your worker thread finishes
_thread.Join();
}
或者你可以在你的停止方法中等待:
override public void Stop()
{
if (thread != null)
{
stopEvent.Set();
thread.Join();
}
}
答案 1 :(得分:0)
为了避免造成这种情况的竞争条件,您可以执行以下操作:
pictureBox1.Invoke(new MethodInvoker(delegate()
{
if (!pictureBox1.IsDisposed)
{
pictureBox1.BackgroundImage = (Image)buf;
}
}));
在UI线程上检查IsDisposed
是很重要的,即在调用的委托内部。