今天我要尝试理解WPF中的多线程进程。 所以我制作了一个只有一个窗口的WPF应用程序。在窗口中,您将找到一个按钮和一个文本框 - 没有别的:
<Window x:Class="Multithreading.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
<TextBox Height="23" Name="txtCounter" VerticalAlignment="Top" Width="120" />
</Grid>
好的 - 让我们来看看我的点击事件:
private void button1_Click(object sender, RoutedEventArgs e)
{
ThreadStart ts = delegate
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(Threddy));
};
new Thread(ts).Start();
}
正如您所看到的,有一个委托方法'Threddy':
public void Threddy()
{
for (int i = 0; i < 10000; i++)
{
txtCounter.Text = "" + i;
}
}
我希望现在很清楚我想要做的事情: 如果用户单击该按钮,则应启动新线程,这将更改文本框的文本。但不幸的是,文本只改变了一次:最后。
所以 - 我做错了什么? 谢谢你的帮助!
CodeCannibal
答案 0 :(得分:0)
我认为你正在开始你的线程异步,并发布你的线程代码异步。 您想要启动另一个线程,并从该更新启动UI线程上的控件。 WPF不允许您更新从另一个线程在UI线程上创建的控件,因此您必须使用调度程序将控制更新代码发布到UI线程。这是Theddy中的Dispatcher包装器。
private void button1_Click(object sender, RoutedEventArgs e) {
ThreadStart ts = new ThreadStart(Threddy);
new Thread(ts).Start();
}
public void Threddy() {
for (int i = 0; i < 10000; i++){
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
txtCounter.Text = "" + i;
}));
}
}
请注意,在循环内部,您可以使用BeginInvoke或Invoke 前者(BeginInvoke)意味着Threddy循环将继续运行并且不等待UI更新 - 将发生(UI更新)但循环不等待它。 UI和循环计数器都有进度但不一定是同步的 后者(Invoke)意味着循环的每次执行都将等待,直到UI控件实际上已更新。 UI和循环计数器已同步。