Note that there are some explanatory texts on larger screens.

plurals
  1. POWPF Event: BitmapImage PropertyChanged: "Calling Thread Cannot access"
    primarykey
    data
    text
    <p>I'm trying to understand what it is about the following code that <b>is</b> perfectly happy with loading a text file and displaying its contents, but <b>isn't</b> happy with loading a BitmapImage and displaying it on a timer.Elapsed event handler. </p> <p>I understand it has to do with the UI thread. </p> <p>But why is this not a problem for the textfile example?</p> <p>First, the XAML:</p> <pre><code>&lt;Window x:Class="WpfApplication7.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"&gt; &lt;StackPanel Orientation="Vertical"&gt; &lt;TextBlock Text="{Binding Path=Message, UpdateSourceTrigger=PropertyChanged}" FontSize="20" Height="40" Width="300" Background="AliceBlue" /&gt; &lt;Image Source="{Binding Path=Image,UpdateSourceTrigger=PropertyChanged}" Height="100" Width="100"/&gt; &lt;/StackPanel&gt; &lt;/Window&gt; </code></pre> <p>and the C#, which raises a PropertyChangedEventHandler on a timer:</p> <pre><code>using System; using System.ComponentModel; using System.Timers; using System.Windows; using System.IO; using System.Windows.Threading; using System.Windows.Media.Imaging; </code></pre> <p>and</p> <pre><code>namespace WpfApplication7 { public partial class Window1 : Window, INotifyPropertyChanged { public BitmapImage Image { get; private set; } public string Message { get; set; } public event PropertyChangedEventHandler PropertyChanged = delegate { }; private Timer timer; public Window1() { InitializeComponent(); this.DataContext = this; this.timer = new Timer { Enabled = true, Interval = 100 }; this.timer.Elapsed += (s, e) =&gt; { //---happy loading from text file. UI updates :) this.Message = File.ReadAllText(@"c:\windows\win.ini").Substring(0, 20); PropertyChanged(this, new PropertyChangedEventArgs("Message")); //---not happy loading a BitmapImage. PropertyChanged unhappy :( // (Don't make me have to: ! ) //Application.Current.Dispatcher.Invoke( //DispatcherPriority.Send, new Action(delegate //{ this.Image = new BitmapImage(new Uri(@"C:\WINDOWS\Web\Wallpaper\Ascent.jpg")); //Edit --Ah hah, thanks Daniel ! // DependencyObject-&gt; Freezable-&gt; Animatable-&gt; // ImageSource-&gt; BitmapSource-&gt; BitmapImage this.Image.Freeze(); //&lt;--- this will fix it, no need for Dispatcher //Without Dispatcher or Freeze() ... right here: //"The calling thread cannot access this object because a different thread owns it." PropertyChanged(this, new PropertyChangedEventArgs("Image")); //})); }; } } } </code></pre> <p>I know I can fix this with a "Application.Current.Dispatcher.Invoke". So fixing it isn't the problem. Not understanding why I should have to is the problem :)</p> <p><i>Similar</i> questions</p> <ul> <li><p><a href="https://stackoverflow.com/questions/36748/asynchronously-loading-a-bitmapimage-in-c-using-wpf">asynchronously loading a BitmapImage in C# using WPF</a></p></li> <li><p><a href="https://stackoverflow.com/questions/590590/making-sure-onpropertychanged-is-called-on-ui-thread-in-mvvm-wpf-app">Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app</a></p></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload