如何创建带调度的任务链?C#异步Task实现可行性咨询
你的异步任务链逻辑问题解答
嘿,作为异步和Task库的新手,你能想到用Task来实现这个调度逻辑已经很棒了,但现有代码确实存在一些问题,没办法满足你想要的需求,我来帮你梳理和修正下:
先说说现有代码的几个问题
- 阻塞调用问题:你在
Main里用了.Wait(),这会阻塞主线程,在异步编程里这是很不好的习惯,还容易引发死锁。C# 7.1及以上版本支持async Main,应该用await来替代。 - 递归调用错误:
GetVersions方法里的await GetVersions()没有传token参数,会导致编译报错,而且这个递归逻辑也不符合你的需求——你需要的是“没有下版本就回到获取token的流程”,而不是一直递归拉版本。 - 缺少循环和定时逻辑:现有代码只是单次调用获取token和版本,没有实现“每1小时获取一次token”的循环,也没处理“获取token成功才拉版本,没下版本就继续循环取token”的流程。
符合需求的实现思路
根据你的需求,我们可以设计一个循环流程:
- 先获取Access Token;
- 如果获取成功,就拉取版本信息;
- 检查版本是否有下一个,没有的话,等待1小时后重新执行第一步;如果有的话,继续拉取下一个版本(这里假设你是要拉完所有有下版本的内容后,再回到定时取token的流程);
- 全程用异步调用,避免阻塞线程。
修正后的代码示例
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
相关产品推荐
相关产品推荐

