Race condition with Dispatcher.Invoke

I have a WritableBitmap and I want to get its dimensions. Because the object is owned by another thread, we have to go through the Dispatcher. I've tried this:

int targetPixelWidth = 0;
int targetPixelHeight = 0;

writeableBitmap.Dispatcher.Invoke(new Action(() =>
{
    targetPixelWidth = writeableBitmap.PixelWidth;
    targetPixelHeight = writeableBitmap.PixelHeight;
}));

// Do something with targetPixelWidth and targetPixelHeight

However, this sometimes fails: the values often remained 0, even though the real values are different.

Thinking it might be a threading issue, I changed the code as follows:

var bitmapInfo = (Tuple<int, int>)writeableBitmap.Dispatcher.Invoke(new Func<Tuple<int, int>>(
   () => Tuple.Create(writeableBitmap.PixelWidth, writeableBitmap.PixelHeight)
));

Debug.Assert(bitmapInfo != null, "Obviously, this should pass.");

targetPixelWidth = bitmapInfo.Item1;
targetPixelHeight = bitmapInfo.Item2;

// Do something with targetPixelWidth and targetPixelHeight

But now, bitmapInfo is sometimes null. Which is strange, because (according to the documentation) Invoke should only return null when the delegate has no return value, which it obviously does in this case. I've even Debug.Asserted the return value of Tuple.Create, and it was never null.

What am I missing here? What causes this race condition, and what can I do about it?

Answers


EDIT

sorry for given the wrong answer.

It seems that you want to get the dependency property of WriteableBitmap which lives in gui thread from another thread.

you can try this:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var writeableBitmap = new WriteableBitmap(100, 100, 300, 300, PixelFormats.Bgra32, null);
        _image.Source = writeableBitmap;

        new Thread(() =>
            {
                Thread.Sleep(1000);

                var pixelHeigth = (Int32)writeableBitmap.Dispatcher.Invoke(
                                                     DispatcherPriority.Background,
                                                    (DispatcherOperationCallback)(arg => ((WriteableBitmap)arg).PixelHeight), writeableBitmap);
                Debug.Print("PixelHeight:" + pixelHeigth);

            }).Start();

    }

I just tried, it works well.


This works, although I don't know why:

ManualResetEventSlim mre = new ManualResetEventSlim(false);

int targetPixelWidth = 0;
int targetPixelHeight = 0;

writeableBitmap.Dispatcher.Invoke(new Action(() =>
{
    try {
        targetPixelWidth = writeableBitmap.PixelWidth;
        targetPixelHeight = writeableBitmap.PixelHeight;
    }
    finally {
        mre.Set();
    }
}));

mre.Wait();
// Do something with targetPixelWidth and targetPixelHeight

Somebody (who posted an answer to this question but later removed it), suggested that Invoke is synchronous on the GUI thread, not on the thread that calls Invoke. If that's true, that would explain why this works. However, the documentation, the books [1, 2] and little toy programs attempting to reproduce this problem, all suggest that this is not the case; Invoke should be synchronous on the calling thread.

I haven't been able to come up with a real explanation; if someone has one, I'm all ears :).

EDIT Replaced my original, somewhat rambling answer with something more coherent.


Need Your Help

How to align label and select box vertically (middle)

css css3 yui-pure-css

For the CSS gurus out there, I cannot figure out the css that makes the first label/select pair not middle align, but the second one does align in the middle.

simple PHP echo not working

php html

I am trying to learn basics of php.So I tried following example as in http://www.w3schools.com/

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.