I have a fairly simple C# WPF application using .NET 5. Basically it sits in the background and times specific events for the end user. The events are built from a xml file that is generated externally.
The application consists of 2 windows, one hidden that does all the thinking. If it detects that an event is due it raises a toast message which when clicked on opens the other window to show the event details to the user. All works fine and runs as expected except after a windows sleep/suspend and resume. We obviously don't want the events to add up upon sleep/suspend and so we close the hidden window and upon resume open it again. No problems there but once the system is resumed and an event is raised the visible window refuses to show. If the visible window is open when sleep/suspend happens then upon resume the whole window is frozen and refuses to respond (only way to close the window is kill the application and restart)
The APP code is as follows :-
public static Forms.NotifyIcon notifyIcon;
public static MainWindow mw;
public static ConfigWindow cw;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
// Obtain any user input (text boxes, menu selections) from the notification
ValueSet userInput = toastArgs.UserInput;
// Need to dispatch to UI thread if performing UI operations
Application.Current.Dispatcher.Invoke(delegate
{
ToastControl.HandleToast(args);
});
};
ConfNotifyIcon();
OpenApp();
}
private void ConfNotifyIcon()
{
notifyIcon = new Forms.NotifyIcon();
notifyIcon.Icon = new System.Drawing.Icon("Images/Wellformation.ico");
notifyIcon.DoubleClick += OnClick;
notifyIcon.ContextMenuStrip = new Forms.ContextMenuStrip();
notifyIcon.ContextMenuStrip.Items.Add("Open", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClick);
notifyIcon.ContextMenuStrip.Items.Add("Close", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnClose);
notifyIcon.ContextMenuStrip.Items.Add(new Forms.ToolStripSeparator());
notifyIcon.ContextMenuStrip.Items.Add("Exit", System.Drawing.Image.FromFile("Images/Wellformation.ico"), OnExit);
}
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Suspend:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareLock();
}), null);
break;
case PowerModes.Resume:
this.Dispatcher.BeginInvoke((Action)(() =>
{
PrepareAwake();
}), null);
break;
default:
break;
}
}
private void PrepareAwake()
{
OpenApp();
ConfNotifyIcon();
notifyIcon.Visible = true;
}
private void PrepareLock()
{
notifyIcon.Dispose();
cw.Close();
}
private void OnExit(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
private void OnClose(object sender, EventArgs e)
{
mw.Close();
}
private void OnClick(object sender, EventArgs e)
{
OpenMain();
}
private void OpenMain()
{
mw = new();
mw.Show();
mw.Activate();
}
public static void OpenApp()
{
cw = new ConfigWindow();
}
The hidden Window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.ConfigWindow"
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:WellformationDesktopApplication"
mc:Ignorable="d"
Title="ConfigWindow" Height="1" Width="1" Visibility="Hidden" WindowState="Minimized">
<Grid>
</Grid>
</Window>
with code as follows :-
Timer at = new();
public ConfigWindow()
{
BuildConfig();
InitializeComponent();
}
public void refreshconfig()
{
myObjects.Clear();
myObjects = NudgeManager.GetNudges();
NudgeHandler(myObjects);
}
public void BuildConfig()
{
myObjects.Clear();
myObjects = GetEvents(); // pulls a list of event names with intervals from the config file
EventHandler(myObjects); //Goes through the list of events and figures out when the next event is due based upon the interval in the configuration
ActionTimer();
}
private void ActionTimer()
{
at.Interval = 60000;
at.Elapsed += ChecktActions;
at.AutoReset = true;
at.Enabled = true;
}
private void ChecktActions(object sender, ElapsedEventArgs e)
{
//Go through the trigger times for all events and see if those time have passed, if they have raise a toast showing the event name.
//If an event is raised reset the trigger time for the event based upon the interval and reset that time.
}
and the visible window XAML is as follows :-
<Window x:Class="WellformationDesktopApplication.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:WellformationDesktopApplication"
mc:Ignorable="d"
ResizeMode="NoResize"
WindowStyle="None"
Title="MainWindow" Height="500" Width="800" Background="{x:Null}" Foreground="{x:Null}" AllowsTransparency="True">
<Grid x:Name="BG">
<TextBlock x:Name="Display" HorizontalAlignment="Left" Margin="546,13,0,0" Text="Show event name and appropriate information about the event here..." VerticalAlignment="Top" FontSize="22"/>
</Grid>
</Window>
With Code as follows :-
public MainWindow()
{
InitializeComponent();
setstyles();
this.MouseLeftButtonDown += delegate { DragMove(); };
}
We know that everything to do with the ConfigWindow works fine, we know it is closed upon suspend and a new one is opened on resume with new timings set and all the appropriate alerts working.
The issue is with MainWindow as after a suspend and resume it cannot be interacted with at all. The open button on the icon does nothing, if the window is opened is is completely frozen and cannot be interacted with in any way, and if a toast is clicked on the window does not open but the rest of the toast handling code works fine around it. This happens on Win8, Win10 and Win11.
Any help out there as I am completely at a loss for how this is happening?
Thanks