4

私は理由を探していましたが、stackoverflow に関するすべてのトピックについて、ビジー状態の UI が理由として示唆されていました。テスト用の非常に基本的なコードがあり、他のことをするのに忙しいはずはないと確信していても、UI を更新しません。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    static double t = 0;
    static double dt = 0.1;

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Timer timer = new Timer(5000);
        timer.Enabled = true;
        timer.Elapsed += new ElapsedEventHandler(Update);
        timer.Start();
    }

    void Update(object sender, ElapsedEventArgs e)
    {
        t = t + dt;
        testBlock1.Text = (t).ToString();
    }
}

デバッグしてtextBlock1.Text更新にブレークポイントを設定したところ、5 秒ごとに中断されましたが、UI は更新されません。コードでわかるように、タイマーを開始するために使用するの上にマウスを移動するButtonと、ボタンは典型的な「マウス オーバー ボタン」アニメーションを表示します。テキストの更新ではなく、なぜそれが起こるのですか?

ここで私の質問を削除しますが、UI が忙しくなくてもこのアプローチが UI を更新しない理由を説明するトピックが見つかりませんでした。そうしないと。

4

2 に答える 2

12

System.Timers.Timerデフォルトでは、UIスレッドにマーシャリングしません。Windowsフォームでは、次のように簡単に実行できます。

Timer timer = new Timer(5000);
timer.SynchronizingObject = this;

...しかし、WPF UI要素は実装されていないため、WPFISynchronizeInvokeでこれが機能しなくなります。

を使用しDispatcherてハンドラー内のUIスレッドにマーシャリングするか、またはを使用しDispatcherTimerて開始することができます。

于 2012-10-24T14:00:36.130 に答える
8

WPFの場合、使用する必要がありますDispatcherTimer-また、投稿した上記のコードでは、イベントが他のスレッドではなく他のスレッドで発生するため、cross threadエラーが発生します。elapsedUI thread

private void button1_Click(object sender, RoutedEventArgs e)
{
   DispatcherTimer timer = new DispatcherTimer();
   timer.Interval = new TimeSpan(0, 0, 5);
   timer.Tick += new EventHandler(timer_Tick);
   timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
   t = t + dt;
   txt.Text = (t + dt).ToString();
}

編集

また、次のような既存のコードを使用して UI Dispatcher でマーシャリングすることもできます -

void Update(object sender, ElapsedEventArgs e)
{
    App.Current.Dispatcher.Invoke((Action)delegate()
    {
        t = t + dt;
        txt.Text = (t + dt).ToString();
    });
}
于 2012-10-24T14:07:03.387 に答える