C# 在另一个线程C中调用函数#

C# 在另一个线程C中调用函数#,c#,multithreading,directshow,rfid,C#,Multithreading,Directshow,Rfid,我不知道怎么说,但我会尽力的 我有一个Windows窗体应用程序,它使用网络摄像头拍摄用户的照片,效果很好,我正在使用这里找到的directshownet库,并使用DxSnap示例拍摄照片 应用程序的下一部分使用RFID标签阅读器,一旦扫描标签,它将调用拍照方法。这就是问题所在,因为RFID侦听方法在GUI线程的单独线程中运行,因为它是一个无限while循环 用于拍照的类将picturebox控件的实例作为其构造函数的参数,该构造函数是在主线程中创建的,我认为这就是问题所在 应用程序的每个部分都

我不知道怎么说,但我会尽力的

我有一个Windows窗体应用程序,它使用网络摄像头拍摄用户的照片,效果很好,我正在使用这里找到的directshownet库,并使用DxSnap示例拍摄照片

应用程序的下一部分使用RFID标签阅读器,一旦扫描标签,它将调用拍照方法。这就是问题所在,因为RFID侦听方法在GUI线程的单独线程中运行,因为它是一个无限while循环

用于拍照的类将picturebox控件的实例作为其构造函数的参数,该构造函数是在主线程中创建的,我认为这就是问题所在

应用程序的每个部分都可以单独工作,但是当我试图调用该方法从侦听器线程中拍摄照片时,所有的麻烦都会发生,应用程序崩溃

有人知道我如何从侦听器线程调用在主线程(拍摄照片)中初始化的对象的方法吗

我尝试过委托和调用,但无法解决这个问题,因为我不想直接操纵控件,而是让对象在主线程中执行

下面是一些代码:

    private Capture cam;
    private int portIndex = -1;
    private ArrayList AlreadyOpenPortList = new ArrayList();
    private byte readerAddr = 0;
    private Thread listenThread;
    IntPtr m_ip = IntPtr.Zero;

    public podiumForm()
    {
        InitializeComponent();

        // scanner and camera startup
        startCam();
        openComs();
        openRF();
        startListening();
    }


 private void startListening()
    {
        listenThread = new Thread(new ThreadStart(this.Listen));
        listenThread.Start();
    }

    /// <summary>
    /// Method of retrieving code tag details from reader
    /// </summary>
    private void Listen()        
    {
        int fCmdRet = 0x30;
        byte state = 1;
        byte AFI = 00;
        byte[] DSFIDAndUID = new byte[9];
        byte cardNumber = 0;
        string strDSFIDAndUID = "";
        byte outputSet;

        if (!GetCurrentUsePort())
        {
            MessageBox.Show("Open ComPort, Please");
            return;
        }


        while (true)
        {
            fCmdRet = StaticClassReaderA.Inventory(ref readerAddr, ref state, ref AFI, DSFIDAndUID, ref cardNumber, portIndex);
            if (fCmdRet == 0)
            {
                outputSet = 0;
                fCmdRet = StaticClassReaderA.SetGeneralOutput(ref readerAddr, ref outputSet, portIndex);
                strDSFIDAndUID = ByteArrayToHexString(DSFIDAndUID).Replace(" ", "");
                outputSet = 3;
                fCmdRet = StaticClassReaderA.SetGeneralOutput(ref readerAddr, ref outputSet, portIndex);
                SavePic(strDSFIDAndUID.Substring(2, 16));
                //MessageBox.Show(strDSFIDAndUID.Substring(2, 16));

                //ShutDown();
            }
        }
    }

private void SavePic(string text)
    {
        Cursor.Current = Cursors.WaitCursor;

        // Release any previous buffer
        if (m_ip != IntPtr.Zero)
        {
            Marshal.FreeCoTaskMem(m_ip);
            m_ip = IntPtr.Zero;
        }

        // here's where it crashes
        // capture image
        m_ip = cam.Click();
        Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
        cam.Dispose();

        // If the image is upsidedown
        b.RotateFlip(RotateFlipType.RotateNoneFlipY);
        pbPic.Image = b;

        Cursor.Current = Cursors.Default;
        MessageBox.Show("Here " + text);
    }


private void startCam()
    {
        const int VIDEODEVICE = 0; // zero based index of video capture device to use
        const int VIDEOWIDTH = 640; // Depends on video device caps
        const int VIDEOHEIGHT = 480; // Depends on video device caps
        const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device

        cam = new Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, pbPic);
    }


// method in capture class
 public IntPtr Click()
    {
        int hr;

        // get ready to wait for new image
        m_PictureReady.Reset();
        m_ipBuffer = Marshal.AllocCoTaskMem(Math.Abs(m_stride) * m_videoHeight);

        try
        {
            m_WantOne = true;

            // If we are using a still pin, ask for a picture
            if (m_VidControl != null)
            {
                // CRASHES HERE with : System.InvalidCastException was unhandled
                // Tell the camera to send an image
                hr = m_VidControl.SetMode(m_pinStill, VideoControlFlags.Trigger);
                DsError.ThrowExceptionForHR(hr);
            }

            // Start waiting
            if (!m_PictureReady.WaitOne(9000, false))
            {
                throw new Exception("Timeout waiting to get picture");
            }
        }
        catch
        {
            Marshal.FreeCoTaskMem(m_ipBuffer);
            m_ipBuffer = IntPtr.Zero;
            throw;
        }

        // Got one
        return m_ipBuffer;
    }
private-Capture-cam;
私有int-portIndex=-1;
私有ArrayList AlreadyOpenPortList=新ArrayList();
专用字节读取器ADDR=0;
私有线程listenThread;
IntPtr m_ip=IntPtr.Zero;
公共讲台表格(
{
初始化组件();
//扫描仪和照相机启动
startCam();
openComs();
openRF();
惊人的倾听();
}
私人监听()
{
listenThread=新线程(newthreadstart(this.Listen));
listenThread.Start();
}
/// 
///从读取器检索代码标记详细信息的方法
/// 
私人监听
{
int fCmdRet=0x30;
字节状态=1;
字节AFI=00;
字节[]DSFIDAndUID=新字节[9];
字节卡号=0;
字符串strDSFIDAndUID=“”;
字节输出集;
如果(!GetCurrentUsePort())
{
MessageBox.Show(“请打开组件”);
返回;
}
while(true)
{
fCmdRet=StaticClassReaderA.Inventory(参考读取器地址、参考状态、参考AFI、DSFIDAndUID、参考卡号、端口索引);
如果(fCmdRet==0)
{
输出集=0;
fCmdRet=StaticClassReaderA.SetGeneralOutput(ref readerAddr,ref outputSet,portIndex);
strDSFIDAndUID=ByteArrayToHexString(DSFIDAndUID)。替换(“,”);
输出集=3;
fCmdRet=StaticClassReaderA.SetGeneralOutput(ref readerAddr,ref outputSet,portIndex);
SavePic(strDSFIDAndUID.Substring(2,16));
//Show(strDSFIDAndUID.Substring(2,16));
//关机();
}
}
}
私有void SavePic(字符串文本)
{
Cursor.Current=Cursors.WaitCursor;
//释放任何先前的缓冲区
如果(m_ip!=IntPtr.Zero)
{
FreeCoTaskMem元帅(m_ip);
m_ip=整数零;
}
//这里就是它崩溃的地方
//捕获图像
m_ip=凸轮。单击();
位图b=新位图(cam.Width、cam.Height、cam.Stride、PixelFormat.Format24bppRgb、m_ip);
cam.Dispose();
//如果图像是上下颠倒的
b、 RotateFlip(RotateFlipType.RotateNoneFlipY);
pbPic.Image=b;
Cursor.Current=Cursors.Default;
MessageBox.Show(“此处”+文本);
}
专用void startCam()
{
const int VIDEODEVICE=0;//要使用的视频捕获设备的从零开始的索引
const int VIDEOWIDTH=640;//取决于视频设备的大小
const int VIDEOHEIGHT=480;//取决于视频设备的大小
const int VIDEOBITSPERPIXEL=24;//由设备确定的BitsPerPixel值
cam=新捕获(视频设备、视频宽度、视频高度、视频比特像素、pbPic);
}
//捕获类中的方法
公共IntPtr Click()
{
国际人力资源;
//准备好等待新映像
m_PictureReady.Reset();
m_ipBuffer=Marshal.allocTaskMem(Math.Abs(m_步幅)*m_视频高度);
尝试
{
m_WantOne=真;
//如果我们使用的是静态pin,请索要图片
if(m_VidControl!=null)
{
//此处崩溃:System.InvalidCastException未处理
//告诉相机发送图像
hr=m_VidControl.SetMode(m_pinStill,VideoControlFlags.Trigger);
DsError.THROWEExceptionForHR(hr);
}
//开始等待
如果(!m_PictureReady.WaitOne(9000,false))
{
抛出新异常(“等待图片超时”);
}
}
抓住
{
FreeCoTaskMem元帅(m_ipBuffer);
m_ipBuffer=IntPtr.Zero;
投掷;
}
//有一个
返回m_-ipBuffer;
}
看看这门课;它允许您在主(UI)线程上以一种不知道该机制实际如何工作的方式分派工作(因此也不知道该机制如何与WinForms和WPF一起工作)。因此,您不需要对要调用的控件进行引用

它是幕后使用的工具(您也可以使用
BackgroundWorker
,这取决于您正在尝试的操作,这稍微容易一些)。

Image Image=(Image)pictureBox.Invoke((Func)委托{return pictureBox.Image;});

答案是Control.Invoke,向我们展示什么不起作用。然后缩小范围并向我们展示相关部分。因此,与其使用自定义线程,不如使用backgroundworker?是的,然后您可以使用它的
P
 Image image = (Image)pictureBox.Invoke ((Func<Image>) delegate { return pictureBox.Image; });