我尝试使用这个recomendations: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属性有什么区别?我该怎么办?
答案 0 :(得分:10)
具体建议: thresholdImage
正在后台线程上创建。在UI线程上创建它,或者在创建它后冻结它。
一般建议:区别在于ImageSource
是DependencyObject
,因此它具有线程关联性。因此,您需要在与您分配它的ImageSource
相同的线程上创建Image
(即UI线程),或者您需要Freeze()
ImageSource
1}}一旦你创建它,从而允许任何线程访问它。
答案 1 :(得分:4)
问题是因为thresholdedImage
是在后台线程中创建的并且在UI线程上使用。
调用Freeze方法可能有所帮助。看到 Updating an Image UI property from a BackgroundWorker thread