You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用异步Task的结果处理事件?求现有方案外的优化思路

更优雅的异步+事件处理方案

你的当前实现依赖共享状态变量协调「狗粮到货」和「狗饥饿」两个事件,存在线程安全隐患,且逻辑分散在不同回调中,维护成本高。下面是更优的实现思路,利用Task异步机制替代共享状态,让逻辑更集中、安全。

核心优化思路

把「狗饥饿事件」通过TaskCompletionSource包装成Task,然后同时等待「狗粮订购Task」和「饥饿Task」,根据哪个先完成执行对应逻辑,完全不需要共享状态变量。

优化后的代码

class Program
{
    public static async Task Main()
    {
        Print("开始。");
        
        var dog = new Dog();
        // 用TaskCompletionSource将饥饿事件转为可等待的Task
        var hungryTaskSource = new TaskCompletionSource<Dog>();
        dog.Hungry += (sender, _) => hungryTaskSource.TrySetResult(sender as Dog);
        
        // 发起狗粮订购(无需额外Task.Run,async方法本身返回Task)
        var foodTask = new Amazon().OrderDogFood();
        
        // 等待两个任务中的任意一个完成
        var completedTask = await Task.WhenAny(foodTask, hungryTaskSource.Task);
        
        if (completedTask == foodTask)
        {
            // 狗粮先到:等狗饿了再喂
            var food = await foodTask;
            Print("狗粮已送达,等待狗狗饥饿...");
            var hungryDog = await hungryTaskSource.Task;
            Print("狗粮到后喂狗");
            hungryDog.Feed(food);
        }
        else
        {
            // 狗先饿:等狗粮到了再喂
            var hungryDog = await hungryTaskSource.Task;
            Print("狗狗饿了,等待狗粮配送...");
            var food = await foodTask;
            Print("狗粮到后喂狗");
            hungryDog.Feed(food);
        }
        
        Console.ReadKey();
    }

    public static void Print(string msg)
    {
        Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + ": " + msg);
    }
}

// 以下类保持原实现不变
class Amazon
{
    public async Task<DogFood> OrderDogFood()
    {
        var r = new Random();
        await Task.Delay(r.Next(500, 5000));
        Program.Print("亚马逊配送狗粮到达。");  
        return new DogFood();
    }
}

class Dog
{
    public event EventHandler Hungry;
    private bool IsHungry = false;

    public Dog()
    {
        _ = Task.Run(async () =>
        {
            var r = new Random();
            await Task.Delay(r.Next(500, 5000));
            Program.Print("狗狗饿了。");
            IsHungry = true;
            Hungry?.Invoke(this, null);
        });
    }

    public void Feed(DogFood food)
    {
        if(!IsHungry)
        {
            throw new ApplicationException("狗狗不饿。");
        }
    }
}

class DogFood
{
}

方案优势

  • 无共享状态,线程安全:避免原代码中静态变量的竞态风险,TaskCompletionSource和Task本身是线程安全的
  • 逻辑集中:所有协调逻辑都在Main方法中,无需分散到事件回调和Task内部,可读性更强
  • 异步原生支持:利用.NET异步机制自然处理两种时序情况,无需手动维护标记变量
  • 代码简洁:去掉冗余的状态变量,减少出错点

内容的提问来源于stack exchange,提问作者Damn Vegetables

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 14:40:48