WPF事件:BitmapImage PropertyChanged:“调用线程无法访问”

时间:2009-04-27 19:13:34

标签: c# wpf xaml

我正在尝试理解下面的代码是什么 非常满意加载文本文件并显示其内容,但不是满意加载BitmapImage并将其显示在timer.Elapsed事件处理程序上。

我理解它与UI线程有关。

但为什么这不是textfile示例的问题?

首先,XAML:

<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">

<StackPanel Orientation="Vertical">

<TextBlock Text="{Binding Path=Message, UpdateSourceTrigger=PropertyChanged}" FontSize="20" Height="40" Width="300"  Background="AliceBlue"  />

<Image Source="{Binding Path=Image,UpdateSourceTrigger=PropertyChanged}" Height="100" Width="100"/>

</StackPanel>
</Window>

和C#,它在一个计时器上引发了一个PropertyChangedEventHandler:

using System;
using System.ComponentModel;
using System.Timers;
using System.Windows;
using System.IO;
using System.Windows.Threading;
using System.Windows.Media.Imaging;

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) =>
      {
        //---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-> Freezable-> Animatable-> 
          // ImageSource-> BitmapSource-> BitmapImage
          this.Image.Freeze();  //<--- 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"));
        //}));
      };
    }
  }
}

我知道我可以用“Application.Current.Dispatcher.Invoke”解决这个问题。所以修复它不是问题。不明白我为什么要这样做是问题:)

类似的问题

3 个答案:

答案 0 :(得分:2)

我认为两种情况之间的关键区别在于BitmapImage是一个依赖对象,这意味着它具有“拥有”线程(创建对象的线程)的概念。当你的主UI线程试图访问在另一个线程上创建的(并拥有)的BitmapImage对象时......繁荣!

另一方面,字符串没有“拥有”线程的概念。

答案 1 :(得分:2)

对于我们这些(像我一样)来到这里寻找如何在线程中实际传递位图的人,请查看

https://stackoverflow.com/a/2672929/745913

答案首先是Freeze()位图。

答案 2 :(得分:1)

我认为这是因为BitmapImage是DispatchObject的;您正在非UI线程上创建DispatcherObject,因此是异常。由于文本不是线程对象,因此您看不到文本赋值的错误。