views:

261

answers:

2

I'm writing an application in WPF (C#) which does long operations on a collection of Bitmaps. To keep my application responsive, I decided to use another thread to perform the operations on bitmaps and report progress on a progressbar in main UI thread. I thought BackgroundWorker would do anything for me, but looks like it won't be that easy.

I have the following code:

public class ImageProcessor
{
    public Collection<WriteableBitmap> Pictures { get; private set; }
    private BackgroundWorker _worker = new BackgroundWorker();

    public ImageProcessor()
    {
        _worker.DoWork += DoWork;
    }

    public void DoLotsOfOperations()
    {
        _worker.RunWorkerAsync();
    }

    private void DoWork(object sender, DoWorkEventArgs e)
    {
        // operations on Pictures collection
    }
}

At runtime I load images using a standard open file dialog into the Pictures collection and then I invoke DoLotsOfOperations() method. But as soon as I try to access any of the properties of a single bitmap I get InvalidOperationException: "The calling thread cannot access the object because different thread owns it".

It is obviosly true - I loaded bitmaps and populated the collection in the UI thread and I try to read collection elements in another thread. So i tried different approaches:

  • I passed the whole collection as a parameter of RunWorkerAsync method and got it back in DoWork method from e.Argument but then when I tried to read properties of a single bitmap I still got the same exception.
  • I tried the same thing, this time passing a single bitmap as backgroundworker's argument and still I couldn't get any of the bitmap's properties, let alone bitmap's pixels.

So how can I access bitmap's data inside another thread (and preferably using BackgroundWorker)?

I don't know, maybe my whole approach is wrong. The general idea I want to achieve is:

  1. User loads bitmaps which are then displayed in a window.
  2. User clicks a button and a long operation on the bitmaps is performed but the UI is responsive (which allows user for example to cancel the opration) and the progress is reported on a progess bar.

Thanks in advance for any help.

+1  A: 

WriteableBitmap has explicit support for threading. But you have to follow the protocol, use the Lock() method in the thread to gain access to the BackBuffer.

Hans Passant
A: 

You can access object created on another thread but only using the invoke method - look up dispatcher.invoke or Control.invoke. I also found Loading Bitmaps: DoEvents and the closure pattern useful as a way of avoiding using additional threads where this was just too much trouble.