在WPF中使用非UI线程从内存流中设置一个图像控件的来源

1 人关注

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

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

所以我按照上面的方法创建了一个线程,并调用了从设备上捕捉图像的方法,并设置了图像控件的来源,如下所示。

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;
                        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 个评论
Gun
你需要使用调度器
@Gun 谢谢你的回答,但正如你所看到的,在我所使用的代码中,它仍然抛出了同样的异常。
c#
wpf
multithreading
live-streaming
fingerprint
Abdullah Malikyar
Abdullah Malikyar
发布于 2015-02-17
2 个回答
Clemens
Clemens
发布于 2015-02-17
已采纳
0 人赞同

BitmapImage不一定需要在UI线程中创建。如果你 Freeze 它,它以后就可以从UI线程访问。因此你也会减少你的应用程序的资源消耗。一般来说,如果可能的话,你应该尝试冻结所有的Freezables,特别是位图。

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;
    Action act = () => { imgLivePic.Source = imageSource; };