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

如何设置Timer实现异步任务循环执行并解决触发失效问题?

问题分析与解决方案

核心问题

你的代码里Main方法启动Timer后,立刻调用了timer.Stop()和timer.Dispose(),而且async Main没有任何阻塞逻辑,程序直接执行到末尾终止,导致Timer的Elapsed事件根本没机会触发。另外,原Timer的固定10秒间隔逻辑,会无视前一次任务是否执行完成就触发下一次,可能导致任务重叠,不符合你“所有任务执行完成后等待10秒再从头开始”的需求。

解决方案

推荐用异步循环实现需求,既满足“启动立即执行”“任务完成后等10秒再循环”,也不会占用过多内存(await Task.Delay会释放当前线程,不会持续占用CPU)。同时修复Main方法的退出逻辑,确保程序在用户输入前保持运行。

修改后的代码:

public class Program
{
    private static OpenSeaApiClient openSeaApiClient;
    private static int counter = 1;

    static async Task Main()
    {
        string apiKey = "myApiKey";
        openSeaApiClient = new OpenSeaApiClient(apiKey);

        Console.WriteLine("Press Enter to exit.");
        // 启动后台循环任务
        var loopTask = RunTaskLoopAsync();

        // 阻塞主线程,防止程序提前退出
        await Console.In.ReadLineAsync();
    }

    private static async Task RunTaskLoopAsync()
    {
        while (true)
        {
            Console.WriteLine($"Counter: {counter++}");

            // 依次执行所有Collection任务
            var KarafuruXhypebeastXatmos = new Collection(openSeaApiClient, "karafuru-x-hypebeast-x-atmos", "0x32F2a60942E7563CFC42766018641C6C6b10830E", OfferVariables.initialValueOfferKarafuruXhypebeastXatmos);
            await KarafuruXhypebeastXatmos.ExecuteAsync();

            var BricktopiansByLawDegree = new Collection(openSeaApiClient, "bricktopians-by-law-degree", "0x9eEeAF684E228C2D5C89435e010acC02c41Dc86B", OfferVariables.initialValueOfferBricktopiansByLawDegree);
            await BricktopiansByLawDegree.ExecuteAsync();

            // 更多实例...

            // 所有任务执行完成后,等待10秒进入下一轮
            await Task.Delay(TimeSpan.FromSeconds(10));
        }
    }
}

关键说明

  1. 异步循环特性:while(true)配合await不会造成内存泄漏或高CPU占用,每次await都会释放当前线程,系统可将线程分配给其他任务,直到延迟结束或任务完成。
  2. 立即执行逻辑:程序启动后loopTask会立刻执行第一轮任务,无需等待Timer触发。
  3. 退出控制:Main方法用await Console.In.ReadLineAsync()阻塞主线程,确保程序在用户按下Enter前持续运行,后台循环任务也会一直执行。
  4. 避免任务重叠:必须等所有任务执行完成后才开始10秒等待,完全避免了任务并行执行的问题,符合你的需求。

如果坚持要用Timer实现(不推荐,因为Timer固定间隔不匹配“任务完成后等待”的场景),可以改为每次任务完成后重启Timer,代码示例:

public class Program
{
    private static OpenSeaApiClient openSeaApiClient;
    private static Timer timer;
    private static int counter = 1;

    static async Task Main()
    {
        string apiKey = "myApiKey";
        openSeaApiClient = new OpenSeaApiClient(apiKey);

        // 初始化Timer,先不启动
        timer = new Timer(async _ => await ExecuteTasksAndRestartTimer(), null, Timeout.Infinite, Timeout.Infinite);
        
        Console.WriteLine("Press Enter to exit.");
        // 立即执行第一轮任务
        await ExecuteTasksAndRestartTimer();

        // 等待用户输入
        await Console.In.ReadLineAsync();
        
        // 清理Timer
        timer.Change(Timeout.Infinite, Timeout.Infinite);
        timer.Dispose();
    }

    private static async Task ExecuteTasksAndRestartTimer()
    {
        Console.WriteLine($"Counter: {counter++}");

        var KarafuruXhypebeastXatmos = new Collection(openSeaApiClient, "karafuru-x-hypebeast-x-atmos", "0x32F2a60942E7563CFC42766018641C6C6b10830E", OfferVariables.initialValueOfferKarafuruXhypebeastXatmos);
        await KarafuruXhypebeastXatmos.ExecuteAsync();

        var BricktopiansByLawDegree = new Collection(openSeaApiClient, "bricktopians-by-law-degree", "0x9eEeAF684E228C2D5C89435e010acC02c41Dc86B", OfferVariables.initialValueOfferBricktopiansByLawDegree);
        await BricktopiansByLawDegree.ExecuteAsync();

        // 更多实例...

        // 所有任务完成后,设置10秒后再次触发Timer
        timer.Change(TimeSpan.FromSeconds(10).TotalMilliseconds, Timeout.Infinite);
    }
}

这个Timer版本的逻辑是:立即执行任务,任务完成后设置Timer在10秒后触发一次,触发时再次执行任务,以此循环,同样能保证任务完成后再等待10秒,不会出现重叠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:39:55