-1

I want to display the time every 5ms, and 'fff' is used in wpf to represent ms.

Why is the fff difference in the code of new TimeSpan(0, 0, 0, 0, 5); displayed result not 5? How is it calculated?

Xaml:

<Grid>
        <ListBox Height="140" HorizontalAlignment="Left" Margin="18,31,0,0" 
                 Name="listBox1" VerticalAlignment="Top" Width="308" />
        <Button x:Name="btn" Click="btn_Click" Height="50" Content=" stop"/>
    </Grid>

Codebehind:

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
         DispatcherTimer timer = new DispatcherTimer();
        public bool What { get; set; }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Start");

            timer.Interval = new TimeSpan(0, 0, 0, 0, 5);
            timer.Tick += new EventHandler(dispatcherTimer_Tick);

            timer.Start();
        }
        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            listBox1.Items.Add(DateTime.Now.Hour.ToString() + ":" +
                DateTime.Now.Minute.ToString() + ":" + DateTime.Now.Second.ToString() + ":"+DateTime.Now.Millisecond.ToString());

            CommandManager.InvalidateRequerySuggested();
            listBox1.Items.MoveCurrentToLast();
            listBox1.SelectedItem = listBox1.Items.CurrentItem;
            listBox1.ScrollIntoView(listBox1.Items.CurrentItem);
        }

        private void btn_Click(object sender, RoutedEventArgs e)
        {
            timer.Stop();
        }
       
    }
}

The result:

3

Update :

  public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            CancellationTokenSource tokenSource = new CancellationTokenSource();
           Task timerTask = RunPeriodically(sendRequest, TimeSpan.FromMilliseconds(num), tokenSource.Token);
            
        }
        private void sendRequest()
        {
            k++;
            datas.Add(DateTime.Now );
       
        }
        async Task RunPeriodically(Action action, TimeSpan interval, CancellationToken token)
        {
            while (k<7)
            {
                action();
                await Task.Delay(interval, token);
            }
        }
wpf
  • 103
  • 6
  • 2
    Your expectation is wrong. A DispatcherTimer does not run with an exact interval of 5 ms. – Clemens Jan 11 '23 at 09:39
  • Relevant remark from the documentation "Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs." – Ralf Jan 11 '23 at 09:39
  • Why do you want a 5ms interval in the first place? It matters. Animations don't use timers for example. A busy UI thread would result in delayed and jerky animations for example. WPF itself offers [transition animation support](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/animation-overview?view=netframeworkdesktop-4.8) out of the box – Panagiotis Kanavos Jan 11 '23 at 09:46
  • The default timers used by any OS (Linux, Mac, Windows) *don't* have high resolution or good skew because they aren't meant for audio/video applications. High CPU usage can delay timer event handlers in all applications. To get smooth multimedia (video, audio, animation) OSs offer special real-time or multimedia timer types that are guaranteed to either fire at specific intervals or not at all. It's better to lose a frame than delay it. Most of the time applications don't use these directly, they tell the OS to play audio or draw animations. – Panagiotis Kanavos Jan 11 '23 at 09:55
  • 200 a second. The ui might not even get to change. – Andy Jan 11 '23 at 11:00

1 Answers1

1

When you set the Interval of the timer to 5 milliseconds, the timer will not be executed every 5 milliseconds. The timer doesn't have that high resolution.

From the documentation:

Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs. This is because DispatcherTimer operations are placed on the Dispatcher queue like other operations. When the DispatcherTimer operation executes is dependent on the other jobs in the queue and their priorities.


Task.Delay also uses a timer internally. The resolution is again not high enough for 5ms intervals.

From the documentation:

This method depends on the system clock. This means that the time delay will approximately equal the resolution of the system clock if the millisecondsDelay argument is less than the resolution of the system clock, which is approximately 15 milliseconds on Windows systems.

NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • Please see the update part in my question, it is also not possible to display the update time every 5ms in Task. Are the reasons the same? – wpf Jan 11 '23 at 09:47
  • 1
    @wpf what is the actual problem you want to solve? People don't want to see a listbox with 20 time values per second. What are you trying to use the timer for? – Panagiotis Kanavos Jan 11 '23 at 09:47
  • I'm trying to figure out that fff is not updating correctly for the 5ms of the code. The example in the question above is just for testing. – wpf Jan 11 '23 at 09:51
  • 1
    `Task.Delay` also uses a timer internally. As you can see here: https://source.dot.net/System.Private.CoreLib/A.html#3d5ce2143a41d705 – NineBerry Jan 11 '23 at 09:56
  • 1
    @wpf no, that's what you assume is relevant. It's not. Users don't care about adding list items every 5ms. Why do you want a 5ms timer? – Panagiotis Kanavos Jan 11 '23 at 09:56
  • 1
    `Task.Delay` uses a thread timer so isn't affected by a blocked UI thread BUT it still doesn't have 5ms resolution nor does it have any skew guarantees. Only special multimedia or real-time timers do. – Panagiotis Kanavos Jan 11 '23 at 09:58