Bonjour
Il faut que tu prennes en comptes un certain nombre de paramètres
Donc supposons un intervalle de 20 ms et un code qui a une durée stable d'environ 5 ms. Ça nous fait déjà une période de 25 ms.
Si à 24 ms le dispatcher est autorisé par Windows à lancer un thread, il ne lancera pas le code du Timer, mais un autre thread. Il attendra que Windows lui donne un nouveau fil d'exécution pour se demander s'il exécute le code du Timer et là ça va se jouer à la priorité.
La solution qui se rapprochera le plus d'une périodicité stable est
Mais malgré ça, tu resteras à la merci de Windows qui pourra choisir de mettre ton fil d'exécution en pause s'il veut et quand il veut.
Un truc dans ce genre
le xaml
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" DataContext="{Binding}"> <Grid DataContext="{Binding .}"> <CheckBox IsChecked="{Binding IsRunning}" VerticalAlignment="top" Margin="5" Height="20" Width="150"> <CheckBox.Style> <Style TargetType="CheckBox"> <Setter Property="Content" Value="Démarrer"/> <Style.Triggers> <DataTrigger Binding="{Binding IsRunning}" Value="True"> <Setter Property="Content" Value="Arrêter"/> </DataTrigger> </Style.Triggers> </Style> </CheckBox.Style> </CheckBox> <TextBlock Text="{Binding ValeurTest, StringFormat='Nombre de passages dans la boucle {0}'}" Margin="20" HorizontalAlignment="Center"/> <TextBlock Text="{Binding Duree, StringFormat='Durée d exécution de la boucle {0} ms'}" Margin="40" HorizontalAlignment="Center"/> </Grid> </Window>
le code behind de la fenêtre
using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); TestBoumBoum test = new TestBoumBoum(); this.DataContext = test; } } }
La classe
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Diagnostics; using System.ComponentModel; namespace WpfApp1 { internal class TestBoumBoum:INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; Thread t; Stopwatch chronoInterne = new Stopwatch(); Stopwatch chronoExterne = new Stopwatch(); private bool isRunning = false; /// <summary> /// Etat bindé sur un checkbox pour lancer le "timer" /// </summary> public bool IsRunning { get { return isRunning; } set { if (isRunning == value) return; isRunning = value; if (isRunning)//on lance le timer { ValeurTest = 0; t = new Thread(new ThreadStart(Boucle)); t.Priority = ThreadPriority.BelowNormal;//à toi de voir si c'est la bonne priority t.Start(); } else PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Duree")); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsRunning")); } } private TimeSpan intervalle = TimeSpan.FromMilliseconds(100); /// <summary> /// Intervalle entre 2 exécutions de code /// </summary> public TimeSpan Intervalle { get { return intervalle; } set { intervalle = value; } } private int valeur = 0; /// <summary> /// Valeur qui sera modifiée par le code du "timer" pour compter le mobre d'exécution lors de ton propre chronométrage /// </summary> public int ValeurTest { get { return valeur; } set { if (value == valeur) return; valeur = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ValeurTest")); } } /// <summary> /// Durée entre le start et le stop, pour calculer la stabilité /// </summary> public double Duree { get { return chronoExterne.Elapsed.TotalMilliseconds; } } private void Boucle() { chronoExterne.Restart(); while(isRunning)//boucle générale, ton timer en somme { chronoInterne.Restart(); //ton code à exécuter ValeurTest++; int attente = 0; //Console.WriteLine(chronoInterne.Elapsed.TotalMilliseconds); while(chronoInterne.Elapsed <= intervalle)//ça c'est pour passer le temps, attention si la durée de ton code est plus longue que 20 ms, dans ce cas on relance de suite. attente++; } } } }
Merci beaucoup. Je vais déjà essayer de comprendre tout cà.
Ha zut, un peu pressé hier, j'ai posté le code en C# et pas en VB.Net.
Tu peux le convertir là
https://lite.qwant.com/?q=C%23+to+vb&client=opensearch