0

今日は、WPF のマルチスレッド プロセスを理解しようとします。そこで、ウィンドウが 1 つしかない非常に小さな 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;
        }
    }

ユーザーがボタンをクリックすると、新しいスレッドが開始され、テキストボックスのテキストが変更されます。しかし残念なことに、テキストは 1 回だけ変更されます。つまり、最後です。

それで - 私は何を間違っていますか?ご協力いただきありがとうございます!

コード人食い人種

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 または Invoke を実行できることに注意してください。
前者 (BeginInvoke) は、Threddy ループが引き続き実行され、UI の更新を待機しないことを意味します。つまり、(UI の更新) は発生しますが、ループは待機していません。UI とループ カウンターは両方とも進行しますが、必ずしも同期しているわけではありません。
後者 (Invoke) は、UI コントロールが実際に更新されるまで、ループの各実行が待機することを意味します。UI とループ カウンターが同期されます。

于 2012-04-26T13:23:16.853 に答える