C#动态多阶段任务的整体进度计算方法问询
动态阶段长进程的整体进度计算方案(C#实现)
问题背景
我有一个长运行进程,进程内的阶段数量动态变化(有时4个阶段,有时7个),可获取每个阶段的完成百分比。外部服务会将进度数据POST到.NET API端点,需要计算整体进度以驱动应用的简易进度指示器。以下是收到的示例进度payload:
{ "Message": "Running simulation for insulation type: DRY, departure time (UTC): 5/11/2023 2:32:08 AM", "Percentage": 0.741, "CurrentStage": 3, "NumStages": 4, "RequestId": "7520a59b-7dc4-4878-9e3e-104ce7da451b", "RunFailed": false, "Results": null }
核心数学逻辑
默认假设每个阶段工作量权重相等,整体进度计算公式为:
整体进度 = (已完成阶段数 / 总阶段数) + (当前阶段完成百分比 / 总阶段数)
其中:
- 已完成阶段数 = CurrentStage - 1(阶段从1开始计数)
- 结果范围为0~1(乘以100可转为百分比展示)
示例计算
以第一个示例payload为例:
- 总阶段数NumStages=4,当前阶段CurrentStage=3,当前阶段完成百分比Percentage=0.741
- 已完成阶段数=3-1=2
- 整体进度=(2/4)+(0.741/4)=0.5+0.18525=0.68525(即68.53%)
当当前阶段为4(最后一个阶段)、完成百分比0.963时:
- 整体进度=(4-1)/4 + 0.963/4=0.75+0.24075=0.99075(即99.08%)
C#实现代码
1. 定义进度数据模型类
创建对应JSON结构的DTO类,用于接收API请求:
public class ProcessProgressDto { public string Message { get; set; } public double Percentage { get; set; } public int CurrentStage { get; set; } public int NumStages { get; set; } public string RequestId { get; set; } public bool RunFailed { get; set; } public object Results { get; set; } }
2. 进度计算方法
实现带参数校验的进度计算静态方法,避免无效输入:
public static class ProgressCalculator { public static double CalculateOverallProgress(ProcessProgressDto progress) { // 参数校验 if (progress.NumStages <= 0) throw new ArgumentException("总阶段数必须大于0", nameof(progress.NumStages)); if (progress.CurrentStage < 1 || progress.CurrentStage > progress.NumStages) throw new ArgumentOutOfRangeException(nameof(progress.CurrentStage), "当前阶段必须在1到总阶段数之间"); if (progress.Percentage < 0 || progress.Percentage > 1) throw new ArgumentOutOfRangeException(nameof(progress.Percentage), "阶段完成百分比必须在0到1之间"); // 计算已完成阶段占比 var completedStagesRatio = (progress.CurrentStage - 1) / (double)progress.NumStages; // 计算当前阶段贡献占比 var currentStageContribution = progress.Percentage / (double)progress.NumStages; // 确保结果不超过100% return Math.Min(completedStagesRatio + currentStageContribution, 1.0); } }
3. API端点使用示例
在.NET API控制器中接收请求并计算进度:
[ApiController] [Route("api/progress")] public class ProgressController : ControllerBase { [HttpPost] public IActionResult ReceiveProgress([FromBody] ProcessProgressDto progress) { if (!ModelState.IsValid) return BadRequest(ModelState); try { var overallProgress = ProgressCalculator.CalculateOverallProgress(progress); // 可将整体进度存储到缓存/数据库,供前端进度指示器获取 return Ok(new { OverallProgress = overallProgress, RequestId = progress.RequestId }); } catch (ArgumentException ex) { return BadRequest(new { Error = ex.Message, RequestId = progress.RequestId }); } } }
扩展说明
若不同阶段工作量权重不同,可修改逻辑:提前定义每个阶段的权重占比(如数组stageWeights,总和为1),整体进度计算公式变为:
整体进度 = 已完成阶段的权重总和 + 当前阶段权重 * 当前阶段完成百分比
例如阶段1权重0.2,阶段2权重0.3,阶段3权重0.3,阶段4权重0.2,当前阶段3完成74.1%:
整体进度=0.2+0.3 + 0.3*0.741=0.5+0.2223=0.7223(即72.23%)
内容的提问来源于stack exchange,提问作者Eric Elliston
相关产品推荐
相关产品推荐

