C# 同步阀门控制程序改造为异步程序的问题咨询
错误原因
该编译报错由async/await的基础使用错误导致,原有业务逻辑结构无需完全重构,仅需按异步语法规范调整方法声明与调用逻辑即可:
await作用于Task<T>类型对象后,返回的结果是T类型,而非Task<T>类型,你将retVal声明为Task<int>类型,自然无法接收await openValve()返回的int值- 方法内部只要使用了
await关键字,方法本身必须添加async修饰符,返回值需要对应从T调整为Task<T>
具体修改方案
1. 优化openValve方法(可选但推荐)
如果你的Modbus依赖库提供了WriteSingleRegisterAsync异步API,优先替换同步写入方法,才能实现真正的IO异步,不阻塞UI线程完成台架数据实时展示:
// 添加async修饰符,返回值改为Task<int> public async Task<int> openValve(int limit) { if(_masterFlowrate >= _instructions - 0.1 && _masterFlowrate <= _instructions + 0.1) { // 异步方法内直接返回int值即可,无需手动封装Task.FromResult return 1; } else { if(valveOpening < limit) { valveOpening++; // 异步Modbus写入添加await await master.WriteSingleRegisterAsync(1, _mdbAdr, Convert.ToUInt16(ouvertureValve)); return 0; } else { return -1; } } }
如果不存在可用的异步Modbus API,你当前使用Task.FromResult封装返回值的写法也可保留;如果需要完全避免阻塞主线程,可将Modbus同步写入逻辑套入Task.Run执行,该场景下使用Task.Run不属于误用。
2. 调整increaseFlow方法
// 添加async修饰符,返回值从int改为Task<int> public async Task<int> increaseFlow() { // retVal直接声明为int类型即可 int retVal = 0; switch(openingStep) { case 1: // await获取int返回值直接赋值 retVal = await Vp.openValve(60); if(retVal > 0) openingStep = 4; else { if(retVal < 0) openingStep = 2; } break; case 2: retVal = await Vg.openValve(); if(retVal > 0) openingStep = 4; else { if(retVal < 0) openingStep = 3; } break; case 3: retVal = await Vm.openValve(); if(retVal > 0) openingStep = 4; else { if(retVal < 0) openingStep = 4; } break; } return retVal; }
3. 上层调用适配
后续调用increaseFlow的regulate方法也按照相同规则调整:添加async修饰符,返回值改为Task/Task<T>,调用increaseFlow时添加await即可,原有业务判断逻辑无需任何改动。
内容的提问来源于stack exchange,提问作者FrougeurPro
相关产品推荐
相关产品推荐

