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

如何创建带调度的任务链?C#异步Task实现可行性咨询

你的异步任务链逻辑问题解答

嘿,作为异步和Task库的新手,你能想到用Task来实现这个调度逻辑已经很棒了,但现有代码确实存在一些问题,没办法满足你想要的需求,我来帮你梳理和修正下:

先说说现有代码的几个问题

  • 阻塞调用问题:你在Main里用了.Wait(),这会阻塞主线程,在异步编程里这是很不好的习惯,还容易引发死锁。C# 7.1及以上版本支持async Main,应该用await来替代。
  • 递归调用错误:GetVersions方法里的await GetVersions()没有传token参数,会导致编译报错,而且这个递归逻辑也不符合你的需求——你需要的是“没有下版本就回到获取token的流程”,而不是一直递归拉版本。
  • 缺少循环和定时逻辑:现有代码只是单次调用获取token和版本,没有实现“每1小时获取一次token”的循环,也没处理“获取token成功才拉版本,没下版本就继续循环取token”的流程。

符合需求的实现思路

根据你的需求,我们可以设计一个循环流程:

  1. 先获取Access Token;
  2. 如果获取成功,就拉取版本信息;
  3. 检查版本是否有下一个,没有的话,等待1小时后重新执行第一步;如果有的话,继续拉取下一个版本(这里假设你是要拉完所有有下版本的内容后,再回到定时取token的流程);
  4. 全程用异步调用,避免阻塞线程。

修正后的代码示例

using System;
using System.Threading.Tasks;
using System.Threading;

public class VersionScheduler
{
    // 模拟获取AccessToken的异步方法
    public async Task<string> GetAccessToken()
    {
        // 这里替换成真实的从服务器获取token的逻辑
        await Task.Delay(100); // 模拟网络请求耗时
        Console.WriteLine("获取到新的Access Token");
        return "fake-token-123";
    }

    // 模拟从服务器获取版本信息的方法,返回包含HasNextVersion的对象
    private async Task<VersionInfo> GetVersionsFromServer(string token)
    {
        // 替换成真实的版本请求逻辑
        await Task.Delay(100);
        // 这里可以根据业务逻辑动态设置HasNextVersion,比如模拟前两次有下版本,之后没有
        var random = new Random();
        var hasNext = random.Next(0, 3) != 0;
        Console.WriteLine($"获取版本信息,HasNextVersion: {hasNext}");
        return new VersionInfo { HasNextVersion = hasNext };
    }

    // 递归拉取所有有下版本的内容
    private async Task FetchAllVersions(string token)
    {
        var version = await GetVersionsFromServer(token);
        if (version.HasNextVersion)
        {
            // 如果有下版本,继续拉取
            await FetchAllVersions(token);
        }
        else
        {
            Console.WriteLine("没有更多版本,等待下一次获取Token");
        }
    }

    // 核心调度逻辑
    public async Task StartScheduler(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                // 1. 获取Access Token
                var accessToken = await GetAccessToken();

                if (!string.IsNullOrEmpty(accessToken))
                {
                    // 2. 获取版本信息(并拉取所有有下版本的内容)
                    await FetchAllVersions(accessToken);
                }
                else
                {
                    Console.WriteLine("获取Access Token失败,等待重试");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"执行过程中出现错误: {ex.Message}");
            }

            // 3. 等待1小时后再次执行(如果没有取消信号)
            await Task.Delay(TimeSpan.FromHours(1), cancellationToken);
        }
    }

    // 版本信息模型
    private class VersionInfo
    {
        public bool HasNextVersion { get; set; }
    }
}

// 主程序入口
class Program
{
    static async Task Main(string[] args)
    {
        var scheduler = new VersionScheduler();
        var cancellationTokenSource = new CancellationTokenSource();

        Console.WriteLine("启动调度系统,按任意键停止...");
        // 启动调度任务
        var schedulerTask = scheduler.StartScheduler(cancellationTokenSource.Token);

        // 等待用户输入停止
        Console.ReadKey();
        cancellationTokenSource.Cancel();
        await schedulerTask;

        Console.WriteLine("调度系统已停止");
    }
}

代码说明

  • 异步Main方法:用async Task Main替代原来的同步Main,避免阻塞,符合异步编程规范。
  • 循环调度:用while循环配合Task.Delay(TimeSpan.FromHours(1))实现每1小时执行一次的逻辑。
  • 递归拉取版本:FetchAllVersions方法会在有下版本时继续拉取,直到没有下版本为止,然后回到循环等待下一次取token。
  • 取消支持:加入CancellationToken方便随时停止调度,避免程序无法正常退出。
  • 错误处理:用try-catch包裹核心逻辑,避免单次错误导致整个调度系统崩溃。

这样调整后,就能完美实现你想要的任务链逻辑啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:57:13