6

私はWPFを使用して非常に単純なストップウォッチに取り組んでいSystem.Diagnosticsますが、アプリケーションからの1秒ごとのシステムクロックが実際のクロックで3秒であるのと比較して、ストップウォッチの使用は非常に遅く、信頼性がまったくありませんでした.

ストップウォッチが遅いことについて調べてみたところ、多くの結果が見つかりましたが、解決策が見つからなかったので、独自のカウンターを考え出すことにしました。

これが私が思いついたもののサンプルです:

System.Windows.Threading.DispatcherTimer _update;
DateTime _started;
bool isRunning = false;

更新スレッド:

_update = new System.Windows.Threading.DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1), System.Windows.Threading.DispatcherPriority.Normal, delegate
{
    if (isRunning)
        iTimer.Content = new DateTime((DateTime.Now - _started).Ticks).ToString("HH:mm:ss");
}, this.Dispatcher);

開始、停止、再開を担当する bToggle と、bReset という別のボタンの 2 つのボタンがあります。

private void bReset_Click(object sender, RoutedEventArgs e)
{
    isRunning = false;
    iTimer.Content = "00:00:00";
    bToggle.Content = "Start";
}

private void bToggle_Click(object sender, RoutedEventArgs e)
{
    if ((string)bToggle.Content == "Start")
    {
        isRunning = true;
        _started = DateTime.Now;
        bToggle.Content = "Stop";
    }
    else if ((string)bToggle.Content == "Resume")
    {
        isRunning = true;
        bToggle.Content = "Stop";
    }
    else
    {
        isRunning = false;
        bToggle.Content = "Resume";
    }
}

開始とリセットは正常に機能しますが、停止して再開すると実際の時間を使用しているため、実際の時間まで秒単位でジャンプします。

この問題をどのように解決できますか、または現在の時刻に実際に正確なストップウォッチの代替手段はありますか?

4

3 に答える 3

2

TimeSpan accumulatedTime誰かが停止をクリックするたびに、経過した間隔を保存する変数を追加する必要があります。

と:

iTimer.Content = (new DateTime((DateTime.Now - _started).Ticks) + accumulatedTime).ToString("HH:mm:ss");
于 2012-05-04T10:56:36.483 に答える
1

使用するSystem.Timers.Timer

これを開始および停止し、タイマーティックイベントでカウンターを設定できます。

これは簡単な例です。

public partial class MainWindow : Window
{
    private Timer _timer;
    private int _time;

    public MainWindow()
    {
        InitializeComponent();

        _time = 0;

        _timer = new Timer(1000);
        _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
    }

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {

        Dispatcher.Invoke(new Action(() =>
                                         {
                                             _time++;
                                             tbTime.Text = _time.ToString();
                                         }));

    }

    private void btnStartStop_Click(object sender, RoutedEventArgs e)
    {
        if (_timer.Enabled)
        {
            _timer.Stop();
        }
        else
        {
            _timer.Start();
        }
    }
}

Xaml:

<Grid>
    <StackPanel>
        <Button Name="btnStartStop" Content="start/stop timer" Click="btnStartStop_Click" />
        <TextBlock Name="tbTime" Text="00:00" />
    </StackPanel>
</Grid>
于 2012-05-04T11:02:56.453 に答える
0

この行があなたの問題だと思います:

_update = new System.Windows.Threading.DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1), System.Windows.Threading.DispatcherPriority.Normal

これは、デリゲートを 1 秒あたり 1000 回実行し、2 番目に高い優先度でスケジュールすることを WPF に指示します。Renderこれはandよりも優先度が高くDataBind、入力した更新された値を実際に表示するには Render と DataBind の両方が必要だと思いますiTimer.Content

DispatcherPriority を Background に設定し、より低い周波数を使用する必要があります (たとえば、20 ミリ秒 - とにかく、人間は 50 fps よりも速いものを見ることはできません)。

于 2012-05-04T11:17:07.777 に答える