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

如何在C#中阻止Quartz.NET定时任务在计算机非活跃时运行?

可行解决方案

针对Windows服务中Quartz任务需要跳过系统非活跃状态执行的需求,可通过结合Windows原生API实现状态校验,在任务执行前判断系统是否活跃,非活跃则直接跳过任务逻辑:

1. 实现系统活跃状态检查逻辑

通过调用两个核心Windows API,分别判断工作站锁定状态和用户输入空闲时长,组合得出当前系统是否处于活跃状态:

1.1 声明所需Windows API

在项目中添加API声明(需引用System.Runtime.InteropServices):

using System.Runtime.InteropServices;

public static class SystemActivityHelper
{
    [StructLayout(LayoutKind.Sequential)]
    private struct LASTINPUTINFO
    {
        public uint cbSize;
        public uint dwTime;
    }

    [DllImport("user32.dll")]
    private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

    [DllImport("wtsapi32.dll")]
    private static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out IntPtr ppBuffer, out uint pBytesReturned);

    [DllImport("wtsapi32.dll")]
    private static extern void WTSFreeMemory(IntPtr pMemory);

    private enum WTS_INFO_CLASS
    {
        WTSSessionState = 11
    }

    private enum WTS_CONNECTSTATE_CLASS
    {
        WTSActive,
        WTSConnected,
        WTSConnectQuery,
        WTSShadow,
        WTSDisconnected,
        WTSIdle,
        WTSListen,
        WTSReset,
        WTSDown,
        WTSInit
    }
}

1.2 编写状态检查方法

在SystemActivityHelper中添加判断逻辑:

public static bool IsSystemActive()
{
    // 优先检查工作站是否锁定
    if (IsWorkstationLocked())
        return false;

    // 检查用户输入空闲时长(示例:超过5分钟则判定为非活跃)
    int idleThresholdMinutes = 5;
    uint idleTimeMs = GetIdleTimeMs();
    return idleTimeMs < idleThresholdMinutes * 60 * 1000;
}

private static uint GetIdleTimeMs()
{
    LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
    GetLastInputInfo(ref lastInputInfo);
    return (uint)Environment.TickCount - lastInputInfo.dwTime;
}

private static bool IsWorkstationLocked()
{
    IntPtr buffer = IntPtr.Zero;
    uint bytesReturned;
    int currentSessionId = System.Diagnostics.Process.GetCurrentProcess().SessionId;

    try
    {
        if (WTSQuerySessionInformation(IntPtr.Zero, currentSessionId, WTS_INFO_CLASS.WTSSessionState, out buffer, out bytesReturned))
        {
            WTS_CONNECTSTATE_CLASS state = (WTS_CONNECTSTATE_CLASS)Marshal.ReadInt32(buffer);
            return state == WTS_CONNECTSTATE_CLASS.WTSDisconnected;
        }
        return false;
    }
    finally
    {
        if (buffer != IntPtr.Zero)
            WTSFreeMemory(buffer);
    }
}

2. 修改Quartz Job执行逻辑

在你的GetNetworkDataJob的Execute方法中,先执行状态检查,非活跃则跳过核心任务:

public class GetNetworkDataJob : IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        // 先校验系统活跃状态
        if (!SystemActivityHelper.IsSystemActive())
        {
            // 可添加日志记录:系统非活跃,跳过本次任务执行
            return;
        }

        // 执行你的核心任务逻辑
        await GetNetworkDataAsync();
    }

    private Task GetNetworkDataAsync()
    {
        // 你的任务实现代码
        return Task.CompletedTask;
    }
}

注意事项

  • 权限说明:若服务运行在LocalSystem账户下,默认具备查询会话信息的权限;若使用自定义账户,需赋予其查询系统会话信息的相关权限。
  • 阈值调整:可根据业务需求修改idleThresholdMinutes的值,自定义用户输入空闲的判定标准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 15:27:21