使用WPF中的非UI线程从Memory Stream设置Image控件的源代码

时间:2015-02-17 09:44:08

标签: c# wpf multithreading live-streaming fingerprint

我正在从指纹扫描仪捕捉图像,我想在图像控件中实时显示捕获的图像。

//Onclick of a Button
 Thread WorkerThread = new Thread(new ThreadStart(CaptureThread));
 WorkerThread.Start();

所以我创建了一个如上所述的线程并调用了从设备捕获图像并按如下方式设置Image控件源的方法。

private void CaptureThread()
    {
        m_bScanning = true;
        while (!m_bCancelOperation)
        {
            GetFrame();
            if (m_Frame != null)
            {

                    MyBitmapFile myFile = new MyBitmapFile(m_hDevice.ImageSize.Width, m_hDevice.ImageSize.Height, m_Frame);
                    MemoryStream BmpStream = new MemoryStream(myFile.BitmatFileData);
                    var imageSource = new BitmapImage();
                    imageSource.BeginInit();
                    imageSource.StreamSource = BmpStream;
                    imageSource.EndInit();
                    if (imgLivePic.Dispatcher.CheckAccess())
                    {
                        imgLivePic.Source = imageSource;
                    }
                    else
                    {
                        Action act = () => { imgLivePic.Source = imageSource; };
                        imgLivePic.Dispatcher.BeginInvoke(act);
                    }
            }

            Thread.Sleep(10);
        }
        m_bScanning = false;
    }

现在,当我运行项目时,它会在行Action act = () => { imgLivePic.Source = imageSource; };上抛出异常说" 调用线程无法访问此对象,因为另一个线程拥有它" 。 我做了一些研究,我发现,如果我想在非UI线程上使用UI控件,我应该使用Dispatcher.Invoke方法,你可以看到我有,但我仍然得到相同的例外。 有人可以告诉我,我做错了什么?

2 个答案:

答案 0 :(得分:1)

不一定需要在UI线程中创建BitmapImage。如果您Freeze它,稍后可以从UI线程访问它。因此,您还将减少应用程序的资源消耗。通常,如果可能,您应该尝试冻结所有Freezable,尤其是位图。

using (var bmpStream = new MemoryStream(myFile.BitmatFileData))
{
    imageSource.BeginInit();
    imageSource.StreamSource = bmpStream;
    imageSource.CacheOption = BitmapCacheOption.OnLoad;
    imageSource.EndInit();
}

imageSource.Freeze(); // here

if (imgLivePic.Dispatcher.CheckAccess())
{
    imgLivePic.Source = imageSource;
}
else
{
    Action act = () => { imgLivePic.Source = imageSource; };
    imgLivePic.Dispatcher.BeginInvoke(act);
}

答案 1 :(得分:0)

BitmapImage本身需要在Dispatcher线程上构建。