C# Wpf TextBox。文本可通过绑定在另一个线程中更新
通常,如果我们有一个C# Wpf TextBox。文本可通过绑定在另一个线程中更新,c#,wpf,multithreading,binding,async-await,C#,Wpf,Multithreading,Binding,Async Await,通常,如果我们有一个框架元素,我们就不能从另一个线程更新它的属性。例如,给定名为MyTextBox的TextBox,我们无法执行以下操作: public async void Button_Click(object sender, RoutedEventArgs e) { await Task.Run(() => { MyTextBox.Background = new SolidBrushColor(Colors.Yellow); } } 因为它抛出了一个异常: 调用线程无法访
框架元素
,我们就不能从另一个线程
更新它的属性。例如,给定名为MyTextBox
的TextBox
,我们无法执行以下操作:
public async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() => { MyTextBox.Background = new SolidBrushColor(Colors.Yellow); }
}
因为它抛出了一个异常
:
调用线程无法访问此对象,因为其他线程拥有它
我们也不能通过绑定
(在另一个线程中)修改背景
因为抛出了相同的异常
现在,这里是“奇怪”的行为。如果您试图直接从另一个线程
更新文本
属性,如下所示:
public async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() => { MyTextBox.Text = "new text"; }
}
<TextBox Text="{Binding BoundText}"/>
它抛出相同的预期异常
,但是如果您像这样绑定文本
属性:
public async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() => { MyTextBox.Text = "new text"; }
}
<TextBox Text="{Binding BoundText}"/>
它神奇地工作
我也注意到了ProgressBar
的Value
属性的这种行为
这是一个bug,还是由设计造成的?为什么
我们也不能通过绑定(在另一个绑定中)修改背景
(螺纹)
事实并非如此。WPFBinding
s会自动将值封送回dispatcher线程(除非它们使用ObservableCollection
s,但这是另一个主题)
尝试通过绑定设置后台
属性时出现无效操作异常
的原因是,您在后台线程上创建了一个SolidColorBrush
,并尝试在调度程序线程上使用它。在返回画笔之前(在任务中)调用该画笔上的Freeze()
,您将不会再得到任何异常,因为任何线程都可以使用“freezed”Freezable
s
另外,这也是为什么对示例中的所有其他属性进行多线程绑定的原因
我们也不能通过绑定(在另一个绑定中)修改背景
(螺纹)
事实并非如此。WPFBinding
s会自动将值封送回dispatcher线程(除非它们使用ObservableCollection
s,但这是另一个主题)
尝试通过绑定设置后台
属性时出现无效操作异常
的原因是,您在后台线程上创建了一个SolidColorBrush
,并尝试在调度程序线程上使用它。在返回画笔之前(在任务中)调用该画笔上的Freeze()
,您将不会再得到任何异常,因为任何线程都可以使用“freezed”Freezable
s
另外,这也是为什么对示例中的所有其他属性进行多线程绑定的原因。我只能想象它的属性更改通知对您有效。BoundText的类型是什么?@sellotape它显然是一个字符串,否则我如何分配“new text”值并将其绑定到text属性?我只能想象它的属性更改通知对您有效。BoundText的类型是什么?@sellotape它显然是一个字符串,否则我如何分配“new text”值并将其绑定到text属性?
public async void SomeOperation()
{
await Task.Run(() => { BoundText = "new text"; }
}