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,还是由设计造成的?为什么

我们也不能通过绑定(在另一个绑定中)修改背景 (螺纹)

事实并非如此。WPF
Binding
s会自动将值封送回dispatcher线程(除非它们使用
ObservableCollection
s,但这是另一个主题)

尝试通过
绑定设置
后台
属性时出现
无效操作异常
的原因是,您在后台线程上创建了一个
SolidColorBrush
,并尝试在调度程序线程上使用它。在返回画笔之前(在
任务中)调用该画笔上的
Freeze()
,您将不会再得到任何异常,因为任何线程都可以使用“freezed”
Freezable
s

另外,这也是为什么对示例中的所有其他属性进行多线程
绑定的原因

我们也不能通过绑定(在另一个绑定中)修改背景 (螺纹)

事实并非如此。WPF
Binding
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"; }
}