Visual c# BackgroundWorker对象目前正在其他地方使用

本文关键字:其他 方使用 目前 BackgroundWorker 对象 Visual | 更新日期: 2023-09-27 18:13:36

大家好,感谢大家阅读我的帖子!我想为我的代码寻求建议,因为经过大量搜索,我找不到任何解决这个特定问题的方法。我在谷歌上搜索过stackoverflow,所有的解决方案都不起作用(或者我不知道如何实现它们)。下面是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Threading ;
    namespace Motion_Detection
    {
         public partial class Form1 : Form
        {
            private FilterInfoCollection VideoCaptureDevices;
            private VideoCaptureDevice FinalVideo;
        private void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            Bitmap video = (Bitmap)eventArgs.Frame.Clone();
            pictureBox1.Image = video;
        }
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
            {
                devicesList.Items.Add(VideoCaptureDevice.Name);
                devicesList.SelectedIndex = 0;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[devicesList.SelectedIndex].MonikerString);
            FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
            FinalVideo.Start();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            pictureBox1.Image = null;
            FinalVideo.Stop();
        }
        private void button3_Click(object sender, EventArgs e)
        {
            worker.RunWorkerAsync();
        }
        private void button4_Click(object sender, EventArgs e)
        {
            worker.CancelAsync();
        }
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            while (!worker.CancellationPending)
            {
                Bitmap map = new Bitmap(pictureBox1.Image); // this line throws the error
                for (int x = 0; x < pictureBox1.Width; x++)
                {
                    for (int y = 0; y < pictureBox1.Height; y++)
                    {
                        Color pixel = map.GetPixel(x, y);
                        if (pixel.R == 255 && pixel.G == 0 && pixel.B == 0)
                        {
                            // detected red pixel
                        }
                    }
                }
                Thread.Sleep(100); // check every 100ms or any other given interval
            }
        }
    }
}

所以我使用Aforge视频插件来访问我的网络摄像头。这部分工作,我可以访问并读取它的流,当我把它转储到picturebox1时,它完美地显示,没有任何延迟。

现在我正在玩弄运动检测,首先,我想看看我是否能检测到出现在相机前的某种颜色的像素。因为我需要循环遍历每个像素,所以我必须把它放在不同的线程上,否则它会一直冻结我的GUI并且显示开始延迟。

问题是,因为我这样做,我不知道如何正确访问图片框。从后台工作器获取图像内容,而不会触发来自标题的错误。有些人在互联网上建议使用锁(),但我从来没有这样做,也不知道我应该锁()在这里。我以前从未使用过多线程,只是因为最后我永远无法处理访问冲突。

为了解决这个问题,我尝试了像try finally块这样的事情,尽管即使在try块中,我也得到了相同的异常。我假设有一种更干净的方法来做我提到的事情,但我真的不知道哪一种方法是正确的。

我希望我在论坛上的第一篇文章尽可能清晰易懂。

Thanks in Regards~ Ilhan

Visual c# BackgroundWorker对象目前正在其他地方使用

你不能/不应该访问pictureBox1,除非在UI线程上。

我认为你需要这样做:

private void GetImage(out Bitmap img)
{
    img = new Bitmap(pictureBox1.Image);
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
    Bitmap img = null;
    Invoke(new Action(() => GetImage(out img)));
    // Do what you want with the bitmap
}

访问winform上的控件,如果它不在UI线程上,将抛出异常。您可以使用picturebox1 . invokerrequired1来确定您是否在正确的线程上。调用Invoke将向UI线程发送一个消息来执行传递的委托,然后它将等待传递的委托完成。调用BeginInvoke会发送消息,但不会等待。