You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现SessionSwitch事件单次日志记录,避免重复输出并保持程序运行

问题分析与解决方案

核心问题拆解

  • 重复日志原因:原代码在while(true)循环中反复注册SessionSwitch事件,导致同一个事件处理器被绑定数百上千次,每次事件触发时,所有绑定的处理器都会执行,自然生成重复日志。
  • 程序退出原因:移除循环后,Main方法执行完毕,控制台程序的主线程直接退出,进程终止,无法继续监听系统事件。

修复步骤

  1. 仅注册一次事件:将事件绑定代码移出循环,放在Main方法开头,确保事件处理器只绑定一次。
  2. 阻塞主线程保持程序运行:使用ManualResetEvent或Console.ReadLine()等方式,让主线程处于等待状态,不直接退出。
  3. 优化日志写入:添加线程锁避免多线程写入冲突,同时增加时间戳提升日志可读性。

修改后的完整代码

using System;
using System.IO;
using System.Threading;
using Microsoft.Win32;

namespace CSharpTutorials
{
    class Program
    {
        // 用于线程同步的锁对象,避免日志写入冲突
        private static readonly object _logLock = new object();

        static void Main()
        {
            // 仅注册一次事件处理器,避免重复绑定
            SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;

            // 使用ManualResetEvent阻塞主线程,无需用户输入即可保持程序运行
            var resetEvent = new ManualResetEvent(false);
            resetEvent.WaitOne();

            // 若需交互式退出,可替换为以下代码:
            // Console.WriteLine("程序已启动,监听会话事件...按回车退出");
            // Console.ReadLine();
        }

        static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            string message = e.Reason switch
            {
                SessionSwitchReason.SessionLogon => "User logged into the session.",
                SessionSwitchReason.SessionLogoff => "User logged off the session.",
                SessionSwitchReason.RemoteConnect => "User remote connected.",
                SessionSwitchReason.RemoteDisconnect => "User remote disconnected.",
                SessionSwitchReason.SessionLock => "User locked the computer.",
                SessionSwitchReason.SessionUnlock => "User unlocked the computer.",
                _ => string.Empty
            };

            if (!string.IsNullOrEmpty(message))
            {
                RecordLog(message);
            }
        }

        private static void RecordLog(string message)
        {
            // 加锁确保多线程下日志写入不会乱序或覆盖
            lock (_logLock)
            {
                using (StreamWriter writer = File.AppendText("log.txt"))
                {
                    // 添加时间戳,提升日志可读性
                    writer.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
                }
            }
        }
    }

    // 原自定义类可保留,不影响功能
    public class MyClass
    {
        public int MyProperty { get; set; }
    }
}

关键修改说明

  • 事件注册优化:把事件绑定代码从死循环中移出,确保处理器只绑定一次,彻底解决重复日志问题。
  • 主线程阻塞方案:用ManualResetEvent.WaitOne()实现无交互的后台运行,避免原死循环的无效CPU占用;如果需要用户手动退出,可替换为Console.ReadLine()。
  • 日志可靠性提升:添加线程锁避免多线程写入冲突,增加时间戳让日志内容更清晰可追溯。

内容的提问来源于stack exchange,提问作者Zac Borders

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:35:46