如何在多个线程中访问 UI 元素?
Posted
技术标签:
【中文标题】如何在多个线程中访问 UI 元素?【英文标题】:How to access UI elements in multiple threads? 【发布时间】:2021-11-21 18:55:31 【问题描述】:我有一个标准的foreach
循环,后来我变成了Parallel.Foreach()
。但是在我的循环中,我有一些区域可以访问 UI 元素并获取和设置 UI 元素信息。
所以当我运行它时,我得到一个错误,我无法访问该元素,因为另一个线程可以访问它。我需要访问多个元素,x:Name
存储在列表中。
我该如何克服这个问题?
Parallel.ForEach(calculatedTestVariables, variable =>
string idName = "id_" + variable.id;
var textBox = this.FindName(idName) as TextBox; //need the text from this TextBox
//some calculations
int x = 1 + 2 + 3 + 4
textBox.Text = x.toString();
);
【问题讨论】:
你应该使用数据绑定和可能的数据模板来避免这种讨厌的代码。 控件具有线程亲和性:您只能从拥有的线程访问它们。出于这个原因,在后台线程上进行 UI 工作是没有意义的。只需将繁重的计算移至后台线程,然后返回 UI 线程以使用结果更新您的 UI。 【参考方案1】:为此,您需要数据绑定。你可以按照这样的方式,
首先创建您的视图模型并更新您的属性:
public class MainViewModel : BindableBase
private string m_TextProgress;
public string TextProgress
get return m_TextProgress;
set SetProperty(ref m_TextProgress, value);
public void Run()
List<Variable> calculatedTestVariables = new List<Variable>();
for (int i = 0; i < 5000; i++)
Variable item = new Variable();
item.id = i;
calculatedTestVariables.Add(item);
Parallel.ForEach(calculatedTestVariables, variable =>
string idName = "id_" + variable.id;
//some calculations
int x = 1 + 2 + 3 + 4;
TextProgress = "" + variable.id + x;
);
设置你的数据上下文
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<StackPanel>
<TextBlock
Width="120"
Height="30"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="Binding TextProgress, UpdateSourceTrigger=PropertyChanged, Mode=OneWay" />
<Button
Width="120"
Height="30"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Calculate" />
</StackPanel>
</Grid>
并从 GUI 端调用您的 Run 方法
【讨论】:
我认为您不需要对示例中的代码进行数据绑定。 @Andy,那会怎么样? 一个任务或方法可以接受一个参数并返回一个结果。您可以从 ui 传入任何您需要的内容,并在处理完成后返回设置 ui 属性所需的任何内容,返回 ui 线程。我可能会在使用视图模型使用 mvvm 时这样做,我也推荐使用 mvvm。但我不认为你绝对必须使用绑定。 是的,在这种情况下绑定不是必须的。他至少应该写一个异步方法。以上是关于如何在多个线程中访问 UI 元素?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Android 中的 Fragment 访问 UI 元素?