-->

Setting source of an Image control from Memory Str

2019-08-15 04:57发布

问题:

I am Capturing image from a finger print Scanner and i want to display the captured image live in an Image control.

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

So i created a thread as above and called the method that captures the image from the device and sets the source of the Image control as follows.

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;
    }

Now when i Run the project it throws an Exception on line Action act = () => { imgLivePic.Source = imageSource; }; Saying "The Calling thread Can Not Access this object because a different thread owns it". i did some research and i found out that if i want to use UI controls over a NON-UI thread i should use Dispatcher.Invoke method, which as you can see i have but i am still getting the same exception. can someone please tell me what am i doing wrong?

回答1:

The BitmapImage does not necessarily need to be created in the UI thread. If you Freeze it, it will later be accessible from the UI thread. Thus you will also reduce the resource consumption of your application. In general, you should try to freeze all Freezables if possible, especially bitmaps.

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);
}


回答2:

The BitmapImage itself needs to be constructed on the Dispatcher thread.