1

私のwp7.5アプリでは、ストップクロックを表示する必要があるブロックがあります(たとえば、30,29,28 ... 1,0)。DispatchTimerクラスとTimerクラスを使用してこれを実現するためにさまざまな実装を試しましたが、いずれも問題を解決しませんでした。

アプローチ1:これがDispatchTimerに使用したスニペットです。

DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 1); // 1 second
dt.Tick += new EventHandler(dt_Tick);

for(int count=0;count<30;count++)
    dt.Start();

void dt_Tick(object sender, EventArgs e)
{
   // my UI control update here
}

Tickイベントの実装では、タイムカウンターを使用してUIコントロールを更新しています。同じトピックに関するいくつかの質問をここで読みました。UIスレッドが原因で、一部のシナリオでディスパッチャティックが起動しない場合があります。それは私にも同じように起こりました、ダニイベントは決して発火しませんでした。

アプローチ2:System.Threading.Timerクラスを使用してみました。

Timer timer = new Timer(TimerProc);

for(int count=0;count<30;count++)
    timer.Change(1000, 0);

void TimerProc(object sender)
{
   // my UI control update here
}

私のアプローチはうまくいきませんでした。繰り返し質問するかもしれませんが、コードのどこで間違っているのか誰かに教えてもらえますか?

4

2 に答える 2

2

keepと呼ばれるafterメソッドは、DispatcherTimer間隔が経過したときからそれを呼び出すときまでを起動します。したがって、30回呼び出す必要はありませんが、カウンターを維持し、ハンドラーで30ティック後にタイマーを停止する必要があります。Start()Tick eventStop()Start()Tick event

private int counter;

private void Start_Click(object sender, RoutedEventArgs e)
{
    counter = 30;
    DispatcherTimer dt = new DispatcherTimer();
    dt.Interval = new TimeSpan(0, 0, 1); // 1 second
    dt.Tick += new EventHandler(dt_Tick);
    dt.Start();
}

void dt_Tick(object sender, EventArgs e)
{
    if (counter >= 0)
    {
        timeText.Text = counter.ToString();
        counter--;
    }
    else
        ((DispatcherTimer)sender).Stop();
}

編集:
DispatcherTimerの精度が十分でない場合は、代わりにSystem.Threading.Timerを使用できますが、この場合Dispatcher.BeginInvoke、tickイベントハンドラーを呼び出して、UIスレッド上のオブジェクトへのアクセスを有効にします。

private int counter;

private void Start_Click(object sender, RoutedEventArgs e)
{
    counter = 30;
    timeText.Text = counter.ToString();
    Timer dt = new Timer(dt_Tick);
    dt.Change(1000 /* delay to start the timer */, 1000 /* period time */);
}

private void dt_Tick(object sender)
{
    if (counter > 0)
    {
        Dispatcher.BeginInvoke(() => timeText.Text = counter.ToString());
        counter--;
    }
    else
        ((Timer) sender).Dispose();
}
于 2011-12-31T12:11:41.930 に答える
0

タイマーティック方式は、時間を追跡する方法ではありません。なんで?2つの理由で。

1 / DispatcherTimerの各ティック間の間隔は正確ではなく、UIで何をするかによって異なります。もう少し長くなるように、1秒になることもあります。

2 /次のティックは、前のティックが終了してから1秒後にトリガーされます。ティック内の更新コードには時間がかかるため、自動的に遅れます。たとえば、更新コードに0.1秒かかる場合、ティックは1秒後にトリガーされ、更新が実行され、次のティックは更新の終了後1秒になるため、タイマーの開始から2.1秒後になります。

したがって、タイマーを開始した時刻を保存し、各ティックでの経過時間を計算する必要があります。

    protected DispatcherTimer Timer { get; set; }

    protected DateTime TimerStartTime { get; set; }

    private void ButtonStart_Click(object sender, RoutedEventArgs e)
    {
        this.Timer = new DispatcherTimer();
        this.Timer.Interval = TimeSpan.FromSeconds(1);
        this.Timer.Tick += this.Timer_Tick;
        this.TimerStartTime = DateTime.Now;
        this.Timer.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        int elapsedSeconds = (int)DateTime.Now.Subtract(this.TimerStartTime).TotalSeconds;

        this.TextTimer.Text = (30 - elapsedSeconds).ToString();
    }

このように、各ティック間の時間が正確でなくても、タイマーが誤った時間を示すことはありません。Tickメソッドを変更せずに、タイマー間隔を500ミリ秒以下に短縮して、より正確なタイマーを作成することもできます。

于 2011-12-31T13:28:20.727 に答える