How to set Image.Source property with Dispatcher?
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 acti开发者_JAVA百科on = 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?
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 a DependencyObject
so it has thread affinity. Therefore, you need to create the ImageSource
on the same thread as the Image
to which you're assigning it (ie. the UI thread), or you need to Freeze()
the ImageSource
once you've created it, thus allowing any thread to access it.
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
精彩评论