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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With