Click here to Skip to main content
15,895,507 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I want to use a simple routine: if user clicks a button, then the button disappears and progress bar shows up. After processing is done, the button becomes visible.
viewModel.StartRendering();
string script = viewModel.LilyScript;
ThreadStart x = delegate
{
    Thread.Sleep(1000); // simulate long processing
    lily.ProcessScript(script);
    Dispatcher.Invoke(new Action(delegate
    {
        viewModel.LilyRenderOutput = lily.ImageSource;
        viewModel.EndRendering();
    }), DispatcherPriority.Normal);
};
Thread thr = new Thread(x);
thr.Name = "Renderowanie";
thr.Start();

The viewModel has dep properties which are bound to controls' properties.
class MainWindowVM
{
...
// (obvious code omitted)
        public Visibility RenderingProgressBarVisibility...
        public static readonly DependencyProperty ...
        public Visibility PaintNotesButtonVisibility...
        public static readonly DependencyProperty ...
        public ImageSource LilyRenderOutput
        internal void StartRendering()
        {
            RenderingProgressBarVisibility = Visibility.Visible;
            PaintNotesButtonVisibility = Visibility.Hidden;
        }

        internal void EndRendering()
        {
            RenderingProgressBarVisibility = Visibility.Hidden;
            PaintNotesButtonVisibility = Visibility.Visible;
        }

}

I got an exception The calling thread cannot access this object because a different thread owns it. on line
viewModel.LilyRenderOutput = lily.ImageSource;

In xaml:
HTML
<Image Source="{Binding LilyRenderOutput}" Stretch="None" />

Interesting fact: the code
C#
Dispatcher.Invoke(new Action(delegate
{
    this.Title="abc";
}), DispatcherPriority.Normal);

does work. Do I use a wrong dispatcher or what? I tried viewModel.Dispather with no success.

Any help appreciated.
Posted
Updated 20-Nov-11 4:15am
v2
Comments
Sergey Alexandrovich Kryukov 19-Nov-11 17:31pm    
How did you get a dispatcher used in the last code sample?
--SA
Lutosław 19-Nov-11 17:57pm    
In the same way and in the same place as the first one. It is a MainWindow's Dispather property. The only difference is in the body of the anymonous method -- it accesses a Title property directly, not through a binding.

1 solution

Root cause is due to the architecture of Windows Presentation Framework.

When working with WPF be aware that if you create a UI object in one thread you can't access it from another thread. Your UI objects should (typically) be created the UI thread, and then you need the UI thread to access them later. No other thread will be able to access objects created on the UI thread.

If you need to access a UI object from another thread you need the UI thread Dispatcher, and then you can use this to invoke calls on the UI thread.

Hope, it clarifies your query.
 
Share this answer
 
Comments
Lutosław 21-Nov-11 17:37pm    
As you have noticed, I am aware of all these UI-related threading issues. However, there is one thing I didn't know: the ImageSource cannot be used from another thread.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900