1

シンプルな秒カウンターを表示しようとしています。ティック間隔が1秒のディスパッチャータイマーと、現在の秒数でティックハンドラーで更新するテキストボックスがあります。tick ハンドラーには少量の作業があります。つまり、一部の int での「tostring()」の呼び出しです。

私の問題は、秒が本来よりも遅いことです。間隔を 100 ミリ秒に設定して経過を確認しても、本来よりも遅くなります。(1 分間で約 6 秒遅くなります)。

正確な2番目のカウンターを表示するために、誰かが私を正しい方向に向けることができますか?

編集: ここにいくつかのコード (.xaml.cs 内)。これは、正常に動作する例から取られています。違いは、別のコントロールの Value プロパティではなく、TextBox の Text プロパティを設定していることです。

...
        this.timer.Interval = TimeSpan.FromMilliseconds(100);
...

    private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
        if (this.currentValue > TimeSpan.Zero) {
            this.currentValue = this.currentValue.Value.Subtract(TimeSpan.FromMilliseconds(100));
        } else {
            // stop timer etc
        }

        this.seconds.Text = this.currentValue.Value.Seconds.ToString();
    }
4

2 に答える 2

8

あなたの時間の追跡方法には欠陥があります。タイマーが刻むたびにカウンターをインクリメントしていますが、タイマーが 100 ミリ秒ごとに実行されるという保証はありません。たとえそうなったとしても、コードの実行時間を考慮に入れる必要があります。したがって、何をしてもカウンターはドリフトします。

あなたがしなければならないことは、カウンターを開始した日付を保存することです。次に、タイマーが刻むたびに、経過した秒数を計算します。

private DateTime TimerStart { get; set; }

private void SomePlaceInYourCode()
{
    this.TimerStart = DateTime.Now;
    // Create and start the DispatcherTimer
}    

private void OnDispatcherTimer_Tick(object sender, EventArgs e) {
    var currentValue = DateTime.Now - this.TimerStart;

    this.seconds.Text = currentValue.Seconds.ToString();
}
于 2013-03-29T08:21:36.770 に答える
1

正確な時間を気にする場合、ディスパッチャータイマーは適切な選択ではありません。

秒数(時間)のカウントと画面への表示を分けるべきだと思います。

System.Threading.Timer を使用し、Timer コールバックで Dispatcher.BeginInvoke() を使用します。

簡単な例:

 public partial class MainPage : PhoneApplicationPage
    {
        private DateTime _startDate;
        private int _secondDuration;
        private Timer _timer;
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            _startDate = DateTime.Now;
            _secondDuration = 0;

            _timer= new Timer(timerCallback, null, 0, 10);

        }

        private void timerCallback(object state)
        {
            var now = DateTime.Now;
            if (now > _startDate + TimeSpan.FromSeconds(1))
            {
                _secondDuration += 1;
                _startDate = now;
                Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });
            }
        }
    }

10ミリ秒ごとにタイマーが1秒経過したことを確認し、経過秒数をテキストボックスに出力します

または、次のように実行できます。

public partial class MainPage : PhoneApplicationPage
{
    private Timer _timer;
    private int _secondDuration;

    // Constructor
    public MainPage()
    {
        InitializeComponent();


        _timer = new Timer(timerCallback, null, 0, 1000);

    }

    private void timerCallback(object state)
    {

        _secondDuration += 1;
        Dispatcher.BeginInvoke(() => { Counter.Text = _secondDuration.ToString(); });

    }
}
于 2013-03-28T17:12:28.960 に答える