I've been stress testing my C# Windows Forms and WPF programs together with "HeavyLoad". HeavyLoad is an application to stress test your PC in order to check if things keep running reliably. Which isn't the case with my program.
What I'm seeing is that whenever I run HeavyLoad, using all available cores, my program starts to lose events. This also happens with the following simple code:
XAML:
<Window x:Class="MultithreadedWPF.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:MultithreadedWPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<TextBox Text="{Binding MyText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</StackPanel>
</Window>
Code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _myText = string.Empty;
/// <summary>
/// This property is bound to a text box in my user interface.
/// </summary>
public string MyText
{
get { return _myText; }
set
{
_myText = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("MyText"));
}
}
public MainWindow()
{
InitializeComponent();
//Create a timer to fire every second.
Timer timer = new Timer(1000);
timer.AutoReset = true;
timer.Elapsed += Timer_Elapsed;
timer.Start();
DataContext = this;
}
/// <summary>
/// The timer's previously elapsed time.
/// </summary>
DateTime previous = DateTime.Now;
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
//Save the current date and time.
DateTime now = DateTime.Now;
//Set the text accordingly.
MyText = $"{now.ToString("HH:mm:ss")}, delta: {now - previous}";
//Save the current time to calculate the next delta.
previous = now;
}
}
This happens in Windows Forms as well as WPF.
What I am seeing:
- When running without HeavyLoad:
- If my program is focused: the delta is around 1 second.
- If my program isn't focused: the delta is around 1 second.
- When running HeavyLoad:
- If my program is focused: the delta is somewhere between 1-3 seconds.
- If my program isn't focused: the delta is somewhere between 3-15 seconds.
This means not only is the user interface not updating, the event in the code behind isn't running or getting lost. Otherwise the delta would always be around 1 second.
The question:
EDIT: I was using the System.Timers.Timer in my example. Not a DispatcherTimer. After switching to a timeapi.h timer (AccurateTimer), I notice that events are delayed instead of missed.
I am using timers as an example. In my other programs the same issues occur with events received from TCP clients. In the real-life scenario's I am getting the same issues without running HeavyLoad, perhaps through Windows Update or other processes. We try to minimize the other processes as much as possible. There are no other programs (except for Windows services and such) running during the execution of our program.
Is there a way around this issue? Perhaps by forcing our program to not run on a certain core? Using a different Windows version (e.g. LTSC, IoT or whatever)?
Putting my program in a higher (or highest) priority does not seem to have enough of an effect.