2

入れ方がわかりませんが、頑張ります。

Webカメラを使用して正常に動作するユーザーの写真を撮るWindowsフォームアプリケーションがあります。ここhttp://directshownet.sourceforge.net/にある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;
    }
4

2 に答える 2

2

SynchronizationContextクラスを見てください。これにより、そのメカニズムが実際にどのように機能するか(したがって、WinFormsおよびWPFで機能する)に依存しない方法で、メイン(UI)スレッドに作業をディスパッチできます。したがって、Invokeを呼び出すためにコントロールへの参照を持っている必要はありません。

これは、舞台裏で使用されるものです(実行しようとしていることによっては、BackgroundWorkerを使用できる場合もあります。これは、操作が少し簡単です)。BackgroundWorker

于 2011-06-19T16:13:52.917 に答える
1
 Image image = (Image)pictureBox.Invoke ((Func<Image>) delegate { return pictureBox.Image; });
于 2011-06-19T16:18:55.007 に答える