开发者

Modifying objects inside a WPF BackgroundWorker for a time-consuming operation

I have question regarding the background worker and showing the UI in an WPF application while a 5-second operation is in progress. I have an object that has to connect to a camera and this connection takes a while (a few seconds). Meanwhile, as this object is trying to connect, I want to display a separate window with a rotating circle (WaitWindow) which suggests that the application is still running, but the user has to wait for a few seconds until the connection is done. So far, so good.

The problems is that I have a timer which every second gets the current image from the camera as a bitmap and displays this bitmap in an Image control on the canvas (_image). So, when this bitmap has to be rendered, the application crashes with this exception:

"Windows has triggered a breakpoint in mywpfapp.exe This may be due to a corruption of the heap, which indicates a bug in mywpfapp.exe or any of the DLLs it has loaded. This may also be due to the user pressing F12 while mywpfapp.exe has focus. The output window may have more di开发者_StackOverflow中文版agnostic information."

I'm thinking it's because of the different threads - the backgroundWorkers's thread that connects to the camera - the UI thread that wants to display the bitmap

The first line of code in which it throws the exception is "source.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);", even though the source seems to be valid.

Here is the code:

public partial class MainWindow
{
    private WaitWindow _waitWindow;
    private ConnectionObject _myConnObject;
    private Timer _myTimer;
    private bool _isConnected;

    public MainWindow()
    {
        _myTimer = new Timer();
        _myTimer.Tick += new EventHandler(TimerEventProcessor);     
    }

    private void btnConnect_Click(object sender, RoutedEventArgs e)
    {
        _isConnected = false;

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += (sender1, e1) =>
        {
            // this takes at least 5 seconds
            _isConnected = _myConnObject.Connect();
        };
        backgroundWorker.RunWorkerCompleted += (sender1, e1) =>
        {
            ConnectEnded();
        };
        backgroundWorker.RunWorkerAsync();

        // show wait window
        _waitWindow = new WaitWindow();
        _waitWindow.Owner = this;
        _waitWindow.ShowDialog();
    }

    private void ConnectEnded()
    {
        if (_waitWindow != null)
        {
            _waitWindow.Close();
            _waitWindow = null;
        }

        if (_isConnected)
        {
            lblStatus.Content = "connected";
        }
        else
        {
            lblStatus.Content = "not connected";
        }
    }

    private BitmapSource TimerEventProcessor(Object myObject, EventArgs myEventArgs)
    {
        if (_isConnected)
        {
            // the bitmap is 
            Bitmap source = _myConnObject.GetBitmapFromDevice();
            if (source == null)
            {
                _image.Source = null;
            }
            else
            {
                MemoryStream ms = new MemoryStream();
                // here it throws an exception
                source.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                ms.Position = 0;
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();
                _image.Source = bi;
            }
        }
    }
}

Do you have any ideas about what's wrong with this code? Or is there a better way to do it?

Thanks a lot!


It could be due to having thread affinity, and that fact that your Timer (currently) is running on a ThreadPool thread, not on the UI thread.

You may want to consider switching to use DispatcherTimer instead. This will cause the timer's events to fire on the UI thread instead of a ThreadPool thread, which would allow you to keep all of the image handling on the main thread.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜