如何在.NET 4.0中替代Task.WhenAny()实现双任务协同逻辑
在.NET 4.0中实现后台计算+每秒心跳的逻辑
针对你在.NET 4.0中模拟新版Task.WhenAny+后台计算+心跳的需求,我们可以利用.NET 4.0原生的Task和WaitHandle机制来实现,完全不需要第三方库。下面是具体的思路和代码实现:
核心思路
- 替代
Task.Run:用.NET 4.0自带的Task.Factory.StartNew启动后台计算任务,这是当时启动异步任务的标准方式。 - 模拟
Task.Delay:通过TaskCompletionSource<T>封装一个延迟完成的Task,内部用Timer实现非阻塞式的延迟,避免浪费线程资源。 - 模拟
Task.WhenAny:获取两个Task的AsyncWaitHandle,用WaitHandle.WaitAny等待任意一个句柄触发,以此判断是计算任务完成还是心跳时间到了。
完整实现代码
using System; using System.Threading; using System.Threading.Tasks; public class CalculationService { // 模拟.NET 4.0版本的Task.Delay private static Task Delay(int millisecondsDelay) { var tcs = new TaskCompletionSource<bool>(); var timer = new Timer(_ => { tcs.TrySetResult(true); }, null, millisecondsDelay, Timeout.Infinite); // 任务完成后自动释放Timer,避免内存泄漏 return tcs.Task.ContinueWith(_ => timer.Dispose()); } public void StartCalculationAndHeartbeats() { // 替代Task.Run启动计算任务 var calculationTask = Task.Factory.StartNew(() => DoTheCalculation()); while (true) { // 创建每秒一次的心跳延迟任务 var heartbeatTask = Delay(1000); // 获取两个任务的等待句柄,用于模拟Task.WhenAny var waitHandles = new[] { calculationTask.AsyncWaitHandle, heartbeatTask.AsyncWaitHandle }; // 等待任意一个任务完成 int completedIndex = WaitHandle.WaitAny(waitHandles); // 检查计算任务状态:完成或故障都需要终止循环并返回结果 if (calculationTask.IsCompleted || calculationTask.IsFaulted) { SendResultToClient(); break; } // 如果是心跳任务完成,发送心跳消息 if (completedIndex == 1) { SendHeartbeatToClient(); } } } // ------------------- 业务逻辑示例方法 ------------------- private void DoTheCalculation() { // 模拟耗时计算,比如持续5秒 Thread.Sleep(5000); } private void SendResultToClient() { Console.WriteLine("计算完成,发送结果给客户端"); } private void SendHeartbeatToClient() { Console.WriteLine("发送心跳给客户端"); } }
关键细节说明
Delay方法的高效性:用Timer而非Thread.Sleep实现延迟,不会阻塞线程池线程,更适合高并发场景,且任务完成后自动释放Timer资源,避免内存泄漏。WaitHandle.WaitAny的作用:这是.NET 4.0原生支持的“等待任意操作完成”的方式,通过Task的AsyncWaitHandle将异步任务的完成事件转化为可等待的信号,完美模拟Task.WhenAny的核心逻辑。- 任务状态的严谨检查:每次等待后都会检查计算任务的状态,无论是正常完成还是异常故障,都会终止循环并向客户端发送结果,保证逻辑的完整性。
内容的提问来源于stack exchange,提问作者Bogey
相关产品推荐
相关产品推荐

