调用方法永不返回

时间:2019-07-03 08:54:33

标签: c# multithreading delegates

我正在运行一个线程,该线程从相机获取图像,将其保存,并更新pictureBox以显示该位图。当我想退出应用程序时,将布尔exitApplication设置为true,但它从未在join()调用中返回。

    public void GrabThread()
    {
        Bitmap copyBmp;
        while (!exitApplication)
        {
            mImage = m_camera.GrabImage();
            SaveImage();

            copyBmp = (Bitmap)mImage.bmp.Clone();
            if (pictureBox1.InvokeRequired)
            {
                pictureBox1.Invoke(new MethodInvoker(
                delegate ()
                {
                    pictureBox1.Image = copyBmp;
                }));
            }
            else
            {
                pictureBox1.Image = copyBmp;
            }
            m_camera.ReleaseImage();
        }
    }

我的退出代码:

        exitApplication = true;
        threadGrab.Join();
        m_camera.Stop();
        Close();

当我从“调试”菜单调用“全部中断”时,线程挂起

pictureBox1.Invoke(new MethodInvoker(
delegate ()
{
    pictureBox1.Image = copyBmp;
}));

为什么?我该如何预防呢?目前,我必须在线程上调用Abort()退出它。

2 个答案:

答案 0 :(得分:1)

此代码陷入僵局,因为pictureBox1.Invoke试图在UI线程中执行代码。不过,该线程被调用threadGrab.Join();

阻止了

可以使用async/await进行修复。 await等待已经执行的异步任务,而不会阻塞Join()的工作方式。完成后,将在原始同步上下文中恢复执行。在WinForms或WPF应用程序中,这意味着将在UI线程上恢复执行。

我假设唯一需要在后台运行的是m_camera.GrabImage();。在这种情况下,代码可能看起来像这样:

public async void Button1_Click(object sender, EventArgs args)
{
    await Task.Run(()=>m_camera.GrabImage();
    //Back in the UI thread
    SaveImage();
    var copyBmp = (Bitmap)mImage.bmp.Clone();
    pictureBox1.Image = copyBmp;
    m_camera.ReleaseImage();
}

Task.Run将在线程池线程中执行m_camera.GrabImage()await将等待完成而不会阻塞UI线程。完成后,将在UI线程中恢复执行,这意味着不需要Invoke

这也可以循环运行:

public async void Capture_Click(object sender, EventArgs args)
{
    while(someCondition)
    {
        await Task.Run(()=>m_camera.GrabImage();

        SaveImage();
        var copyBmp = (Bitmap)mImage.bmp.Clone();
        pictureBox1.Image = copyBmp;
        m_camera.ReleaseImage();
    }
}

答案 1 :(得分:0)

这可能不是正确的答案,但是您可以同时使用OnClosing和OnClosed来停止相机,然后关闭您的应用程序,我不知道它在Winform中是否可以工作,但在WPF中可以与我一起工作

protected override void OnClosing(CancelEventArgs e)
{

            e.Cancel = false; //prevent your application to shutdown
            Camera.Stop(); //stop your camera
            base.OnClosing(e);

}

protected override void OnClosed(EventArgs e)
{
            base.OnClosed(e);
            Application.Current.Shutdown(); //then shutdown again
}

通过2步,您的相机将停止运行,而无需加入任何线程。并且请注意,这段代码是用Wpf编写的,而不是Winform编写的,但我认为您可以在Winform中找到类似的方法

希望这个答案可能对您有所帮助。