0

今天我将尝试了解 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;
        }
    }

我希望现在很清楚我要做什么:如果用户单击按钮,则应该启动一个新线程,这会更改我的文本框的文本。但不幸的是,文本只改变了一次:最后。

那么 - 我做错了什么?谢谢你的帮助!

代码食人族

4

1 回答 1

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 OR Invoke。
前者(BeginInvoke)意味着 Threddy 循环将继续运行并且不会等待 UI 更新 - (UI 更新)会发生但循环不会等待它。UI 和循环计数器都在进步,但不一定同步。
后面的(调用)意味着循环的每次执行都将等到 UI 控件实际更新。UI 和循环计数器已同步。

于 2012-04-26T13:23:16.853 回答