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

C#实现定时文件夹检测:主线程退出致任务仅执行一次的解决办法

解决方案

方法1:让主线程阻塞等待输入

最简单的方式是在Main方法末尾添加控制台输入等待,让主线程保持存活,直到用户主动终止程序(比如按任意键)。

修改后的Main方法:

static void Main(string[] args)
{
    CheckForNewFolders();
    Console.WriteLine("程序已启动,按任意键退出...");
    Console.ReadKey(); // 主线程在此阻塞,直到用户按键
}

方法2:使用异步Main方法(C# 7.1+)

从C# 7.1开始,控制台应用的Main方法支持异步返回类型(async Task),可以直接等待异步任务,避免后台线程被主线程终止。

首先调整CheckForNewFolders方法为异步方法,去掉多余的Task.Run:

private static async Task CheckForNewFoldersAsync()
{
    while (true)
    {
        NewFoldersChecker.CheckForNewFolders();
        await Task.Delay(TimeSpan.FromMinutes(10)); // 用TimeSpan替代硬编码毫秒值,可读性更强
    }
}

然后修改Main方法为异步:

static async Task Main(string[] args)
{
    await CheckForNewFoldersAsync();
    // 因为是无限循环,此处代码永远不会执行,主线程会持续等待任务运行
}

方法3:使用信号量控制主线程生命周期

如果需要更灵活的退出控制(比如监听Ctrl+C事件优雅退出),可以用ManualResetEventSlim让主线程阻塞,直到收到退出信号。

示例代码:

private static readonly ManualResetEventSlim _exitEvent = new ManualResetEventSlim(false);

private static async Task CheckForNewFoldersAsync()
{
    while (!_exitEvent.IsSet)
    {
        NewFoldersChecker.CheckForNewFolders();
        await Task.Delay(TimeSpan.FromMinutes(10));
    }
}

static void Main(string[] args)
{
    // 启动定时任务
    _ = CheckForNewFoldersAsync();

    Console.WriteLine("程序已启动,按Ctrl+C退出...");
    // 监听Ctrl+C退出事件
    Console.CancelKeyPress += (sender, e) =>
    {
        e.Cancel = true; // 取消默认强制退出行为
        _exitEvent.Set(); // 触发退出信号
    };

    _exitEvent.Wait(); // 主线程阻塞,直到退出信号被设置
    Console.WriteLine("程序正在退出...");
}

补充优化点

  • 原代码中用Task.Run包裹async lambda属于多余操作,直接使用异步方法更高效。
  • 若后续需要更复杂的定时调度(如任务暂停、精确执行时间),可以考虑使用System.Threading.Timer,但当前场景下上述基础方案已足够满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:18:10