I have a C# Windows Forms Application on .NET 4.5.
This application connects to a USB Device.
I want to support multiple sessions at the same time.
In order to do so, I need to disconnect from that device on session lock to allow the new session to connect to it.
I used SystemEvents.SessionSwitchEventArgs.Reason to detect such events: - SessionSwitchReason.ConsoleDisconnect on session switch - SessionSwitchReason.ConsoleConnect on unlock after session switch
This event seemed like the perfect solution but sometimes at random times (after a number of locks or unlocks), the event doesn't get fired and the UI freezes. It's worth noting that this doesn't happen when the application is running in the debugger.
I know from the logs that some other background threads are still working normally but the UI freezes and the subscribed function to the event doesn't get called.
A sample of my code:
Program.cs:
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyProgram
{
static class Program
{
private static Mutex mutex = null;
[STAThread]
static void Main()
{
const string appName = "MyProgram";
bool createdNew;
mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
return;
}
Application.EnableVisualStyles();
//This was one attempt to solve the UI deadlock Microsoft.Win32.SystemEvents.UserPreferenceChanged += delegate { };
Application.SetCompatibleTextRenderingDefault(false);
MyProgramEngine MyProgramEngine = new MyProgram.MyProgramEngine();
Application.Run(MyProgramEngine.getForm());
}
}
}
MyProgramEngine:
using log4net;
using log4net.Config;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using WindowsInput;
using System.Windows.Forms;
using Microsoft.Win32;
namespace MyProgram
{
class MyProgramEngine
{
private MainForm mainForm;
public MyProgramEngine()
{
XmlConfigurator.Configure();
Utility.logger.Info(string.Format("MyProgram Started. Version: {0}", Application.ProductVersion));
SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
if (!GlobalSettings.getInstance().isProperlyConfigured())
{
WarningForm warningForm = new WarningForm("MyProgram is not properly configured. Please contact support");
warningForm.ShowDialog();
Application.Exit();
Environment.Exit(0);
}
mainForm = new MainForm();
initArandomBackgroundThread();
initDeviceThread();
}
private void initDeviceThread()
{
Thread detectAndStartReader = new Thread(initDevice);
detectAndStartReader.IsBackground = true;
detectAndStartReader.Start();
}
public void initDevice()
{
//Connect to device
//Start device thread
}
public MainForm getForm()
{
return mainForm;
}
//Handles session switching events
internal void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
try
{
if (e.Reason.Equals(SessionSwitchReason.ConsoleDisconnect))
{
DisconnectFromDevice();
TerminateDeviceThread();
}
else if (e.Reason.Equals(SessionSwitchReason.ConsoleConnect))
{
initDeviceThread();
}
else
{
Utility.logger.Info("The following SesseionSwitchReason has been caught: " + e.Reason + " , No action!");
}
}
catch (Exception ex)
{
Utility.logger.Error("Something bad happened while managing session switching events", ex);
}
}
}
Note: I have not interest in SessionSwitchReason.SessionUnlock or SessionSwitchReason.SessionLock because both I don't want any action on session lock and unlock on the same session.
Thanks for the support!