【发布时间】:2017-08-16 07:49:22
【问题描述】:
我有一个基于 .NET 4.5 的 C# Windows 窗体应用程序。
此应用程序连接到 USB 设备。
我想同时支持多个会话。
为此,我需要在会话锁定时断开与该设备的连接,以允许新会话连接到它。
我使用 SystemEvents.SessionSwitchEventArgs.Reason 来检测此类事件: - 会话切换时的 SessionSwitchReason.ConsoleDisconnect - SessionSwitchReason.ConsoleConnect 在会话切换后解锁
此事件似乎是完美的解决方案,但有时在随机时间(在多次锁定或解锁之后),该事件不会被触发并且 UI 会冻结。 值得注意的是,当应用程序在调试器中运行时,这不会发生。
我从日志中知道,其他一些后台线程仍在正常工作,但 UI 冻结并且未调用事件的订阅函数。
我的代码示例:
程序.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());
}
}
}
我的程序引擎:
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);
}
}
}
注意:我对 SessionSwitchReason.SessionUnlock 或 SessionSwitchReason.SessionLock 不感兴趣,因为我不希望在同一会话上对会话锁定和解锁进行任何操作。
感谢支持!
【问题讨论】:
-
关于 SystemEvents 类引起的问题,请参阅 this answer 中的 CheckSystemEventsHandlersForFreeze() 函数,它可以帮助找到根本原因,即导致冻结的确切控件。
标签: c# .net multithreading session freeze