WPF多线程属性更新不起作用

时间:2012-04-26 12:54:52

标签: wpf multithreading asynchronous

今天我要尝试理解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

1 个答案:

答案 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和循环计数器已同步。