如何使用 Dispatcher 设置 Image.Source 属性?
我尝试使用此建议: http://msdn.microsoft.com/en-us /library/ms741870.aspx(“使用后台线程处理阻塞操作”)。
这是我的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
;
}
private void Process()
{
// some code creating BitmapSource thresholdedImage
ThreadStart start = () =>
{
Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action<ImageSource>(Update),
thresholdedImage);
};
Thread nt = new Thread(start);
nt.SetApartmentState(ApartmentState.STA);
nt.Start();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
button1.Content = "Processing...";
Action action = new Action(Process);
action.BeginInvoke(null, null);
}
private void Update(ImageSource source)
{
this.image1.Source = source; // ! this line throw exception
this.button1.IsEnabled = true; // this line works
this.button1.Content = "Process"; // this line works
}
}
在标记行中,它抛出 InvalidOperationException“由于调用线程无法访问该对象,因为另一个线程拥有它。”。但如果我删除这一行,应用程序就可以工作。
XAML:
<!-- language: xaml -->
<Window x:Class="BlackZonesRemover.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:BlackZonesRemover"
Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightBlue">
<Image Name="image1" Stretch="Uniform" />
</Border>
<Button Content="Button" Grid.Row="1" Height="23" Name="button1" Width="75" Margin="10" Click="button1_Click" />
</Grid>
</Window>
Image.Source 属性与 Button.IsEnabled 和 Button.Content 属性之间有什么区别?我能做些什么?
I tried use this recomendations: http://msdn.microsoft.com/en-us/library/ms741870.aspx ("Handling a Blocking Operation with a Background Thread").
This is my code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
;
}
private void Process()
{
// some code creating BitmapSource thresholdedImage
ThreadStart start = () =>
{
Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action<ImageSource>(Update),
thresholdedImage);
};
Thread nt = new Thread(start);
nt.SetApartmentState(ApartmentState.STA);
nt.Start();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
button1.Content = "Processing...";
Action action = new Action(Process);
action.BeginInvoke(null, null);
}
private void Update(ImageSource source)
{
this.image1.Source = source; // ! this line throw exception
this.button1.IsEnabled = true; // this line works
this.button1.Content = "Process"; // this line works
}
}
In marked line it throws InvalidOperationException "due to the calling thread cannot access this object because a different thread owns it.". But application works if I remove this line.
XAML:
<!-- language: xaml -->
<Window x:Class="BlackZonesRemover.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:BlackZonesRemover"
Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightBlue">
<Image Name="image1" Stretch="Uniform" />
</Border>
<Button Content="Button" Grid.Row="1" Height="23" Name="button1" Width="75" Margin="10" Click="button1_Click" />
</Grid>
</Window>
What difference between Image.Source property and Button.IsEnabled and Button.Content properties? What can I do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
具体建议:
thresholdImage
正在后台线程上创建。要么在 UI 线程上创建它,要么在创建后冻结它。一般建议: 区别在于
ImageSource
是DependencyObject
,因此它具有线程关联性。因此,您需要在与要分配的Image
相同的线程(即 UI 线程)上创建ImageSource
,或者您需要Freeze()
ImageSource 一旦你创建了它,从而允许任何线程访问它。
Specific advice:
thresholdImage
is being created on a background thread. Either create it on the UI thread, or freeze it once it has been created.General advice: The difference is that
ImageSource
is aDependencyObject
so it has thread affinity. Therefore, you need to create theImageSource
on the same thread as theImage
to which you're assigning it (ie. the UI thread), or you need toFreeze()
theImageSource
once you've created it, thus allowing any thread to access it.问题是因为
thresholdedImage
是在后台线程中创建并在 UI 线程上使用的。调用 Freeze 方法可能会有所帮助。看
从BackgroundWorker线程更新图像UI属性
The problem is because
thresholdedImage
is created in the background thread and used on UI thread.Calling Freeze method might help. See
Updating an Image UI property from a BackgroundWorker thread