Question

I'm trying to get a lot of images from a webserver, so not to overload the server with hundreds of requests per second I only let a few through which is handled in WebService. The following code is on the object that saves the image, and where all the binding goes to.

ThreadStart thread = delegate()
{
    BitmapImage image = WebService.LoadImage(data);

    Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
    {
        this.Image = image;
    }));
};

new Thread(thread).Start();

The image is loaded just fine, the UI works fluidly while the image loads, however this.Image = image is never called. If I use Dispatcher.CurrentDispatcher.Invoke(..) the line is called, but doesn't work for setting the Image. Why doesn't the dispatcher invoke my action?

Was it helpful?

Solution

Since you create you BitmapImage on a worker thread, it's not owned by the WPF thread. Maybe this code can help you to solve the issue:

The code you posted

ThreadStart thread = delegate()
{
    BitmapImage image = WebService.LoadImage(data, Dispatcher.CurrentDispatcher);

    Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
    {
        this.Image = image;
    }));
};

new Thread(thread).Start();

How you could change your WebService.LoadImage to "make it work"

BitmapImage LoadImage(object data, Dispatcher dispatcher)
{
    // get the raw data from a webservice etc.
    byte[] imageData = GetFromWebserviceSomehow(data);

    BitmapImage image;

    // create the BitmapImage on the WPF thread (important!)
    dispatcher.Invoke(new Action(()=>
    {
        // this overload does not exist, I just want to show that
        // you have to create the BitmapImage on the corresponding thread
        image = new BitmapImage(imageData);
    }));

    return image;
}

OTHER TIPS

System.Object
    |-> System.Windows.Threading.DispatcherObject
        |-> System.Windows.DependencyObject
            |-> System.Windows.Freezable
                |-> ... 
                    |-> System.Windows.Media.Imaging.BitmapImage

BitmapImage is thread affined. So this control and BitmapImage object should be created in the same thread. Also you can try to just Freeze image, but it seems it will not help.

BeginInvoke does not reveal error because it is handled by WPF. See MSDN how to set up WPF tracing.

WPF is single threaded. Read some book about WPF where all staff described.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top