C# Task&Await场景下如何控制自定义函数仅在Task.WhenAll时执行
问题原因说明
- Task默认行为:返回
Task/Task<T>的普通异步方法,调用即执行,不会等待await关键字才启动,所以你在写var task1 = SimulateJob();的时候方法就已经开始运行了。 - 你现有
SimulateJob方法存在逻辑错误:内部Task.Delay(10000);没有加await,Delay逻辑完全不生效,方法会同步执行完成直接返回结果。 - 重复调用的问题一般是按钮点击事件被重复触发、方法被其他逻辑多次调用导致,可以通过加执行状态锁解决。
修正后代码
首先调整方法逻辑,用Func<Task<T>>任务工厂实现延迟执行,只有你主动调用委托的时候才会启动SimulateJob:
// 增加类级别的执行状态标记,防止重复调用 private bool _isJobRunning = false; private async void button1_Click(object sender, EventArgs e) { // 已经在执行就直接返回,避免重复调用 if (_isJobRunning) return; bool retvalue = false; var periodTimeSpan = TimeSpan.FromSeconds(10); try { _isJobRunning = true; // 这里只存方法委托,不会触发SimulateJob执行 Func<Task<bool>> jobFactory = SimulateJob; var task2 = Task.Delay(periodTimeSpan); // 到此处才调用委托,正式启动SimulateJob var task1 = jobFactory(); await Task.WhenAll(task1, task2); retvalue = task1.Result; } finally { // 执行完成重置状态 _isJobRunning = false; } } // 修正SimulateJob为异步方法,添加await private async Task<bool> SimulateJob() { bool status = false; // 加await才会真正触发延迟逻辑,替换成你实际的Excel加载代码即可 await Task.Delay(10000); status = true; return status; }
修正说明
- 用
Func<Task<bool>>存储方法引用,不会触发方法执行,完美控制SimulateJob的启动时机,符合你要求的到对应逻辑点才执行的需求。 - 修正了
SimulateJob的异步逻辑错误,保证异步逻辑正常执行不阻塞UI。 - 添加了执行状态锁,彻底解决重复调用导致的业务异常问题。
内容的提问来源于stack exchange,提问作者user15940620
相关产品推荐
相关产品推荐

