我有一个c ++ / cli包装类,它从相机中抓取帧并将它们作为事件发送。
WPF测试应用程序启动相机并更新图像。
当我点击Stop
时,它通常会在m->streamThread->Join()
上以死锁结束。我怀疑这个问题与WPF中的帧处理事件有关,而不是与包装器代码有关。
namespace WpfTestApp
{
public partial class Window1 : Window
{
private void OnFrameArrived(object sender, EventArgs e)
{
Action a = delegate
{
// this uses Imaging.CreateBitmapSourceFromMemorySection
// to copy the frame data to the image memory
m_colorImage.UpdateImage(e.Image);
};
Dispatcher.Invoke(a);
}
private void startBtn_Click(object sender, RoutedEventArgs e)
{
m_camera.FrameArrived += m_frameHandler;
m_camera.Start();
}
private void Stop()
{
m_camera.FrameArrived -= m_frameHandler;
m_camera.Stop();
}
}
}
// Camera.h
public ref class Camera
{
public:
delegate void FrameArrivedHandler(Object^ sender, DGEventArgs^ e);
event FrameArrivedHandler^ FrameArrived;
void Start();
void Stop();
private:
void StreamThreadWorker();
Thread^ m_streamThread;
bool m_isStreaming;
}
// Camera.cpp
void Camera::Start()
{
if (m_isStreaming)
return;
m_isStreaming = true;
m_streamThread = gcnew Thread(gcnew ThreadStart(this, &Camera::StreamThreadWorker));
m_streamThread->Start();
}
void Camera::Stop()
{
if (!m_isStreaming)
return;
m_isStreaming = false;
m_streamThread->Join(); // stuck here
}
void Camera::StreamThreadWorker()
{
EventArgs^ eventArgs = gcnew EventArgs();
while (m_isStreaming)
{
eventArgs->Image = Camera->GetImage();
FrameArrived(this, eventArgs);
}
}
答案 0 :(得分:2)
可能发生的情况是:单击“停止”,这将在WPF ui调度程序线程中处理。所以Join
调用是在ui调度程序线程中。但是,同一个线程也负责绘制帧(对UpdateImage的调用调用)。因此,StreamThreadWorker
正在等待FrameArrived
完成,但由于线程正在等待Stop
完成,因此无法完成。这是你的僵局。
因此,为了让StreamThreadWorker
完成,Stop
不得阻止它。实现此目的的一种简单方法是从另一个线程中停止线程:
void Camera::Stop()
{
...
gcnew Thread( gcnew ThreadStart( this, &Camera::DoStopThread ) )->Start();
}
void Camera::DoStopThread()
{
if( !m_streamThread.Join( 3000 ) )
HandleThreadDidNotStopInTimeError(); //notify listeners there's a serious problem
m_streamThread.Abort();
m_streamThread = null;
RaiseThreadStoppedEvent(); //notify listeners that the thread stopped
}