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

我在CPU密集型灯泡生产模拟中是否正确使用async/await?

异步await使用场景解析(结合灯泡生产模拟程序)

我用C#写了一个灯泡生产模拟程序:用户在命令行输入1,就启动异步函数模拟生产10000个灯泡,其中5%是次品;检测到次品时,观察者会收到通知并在控制台输出消息。我发现如果在prod.startMaschine(maschineID);前加await,程序就没法正常运行,所以去掉了这个关键字。想搞懂什么时候该用await,什么时候不该用,结合我的代码解释下。

Console.WriteLine("Bulb Production Monitoring!");
Main();
static async Task Main() {
    string input = "";
    int maschineID = 1;
    Production prod = new Production();
    Console.WriteLine("1: starts a production maschine");
    Console.WriteLine("2: exits the production process");
    while(!input.Equals("exit")) {
        input=Console.ReadLine();
        switch(input) {
            case "1": 
                prod.registerObserver(new Observer());
                prod.startMaschine(maschineID); 
                maschineID++; 
                break;
            case "2" : 
                input="exit"; break;
            default: 
                break;
        }
    }
}
    
public class Bulb {
    public bool _functionTest;
}
    
public class Production {
    private List<Observer> _observerList = new List<Observer>();
    public async Task startMaschine(int maschineId) {
        Console.WriteLine($"Maschine {maschineId} is ready for use ... ");
        int i=0;
        Random rndGenerator = new Random();
        await Task.Run(
            async ()=> {
                while(i<10000) {
                    int rndNumber=rndGenerator.Next(1,101);
                    Bulb bulb = new Bulb();
                    await Task.Delay(2000);
                    if (rndNumber<=5) {
                        bulb._functionTest=false;
                        this.notify(maschineId);
                    }
                    else {
                        bulb._functionTest=true;
                    }
                }
            }
        );
    }
    
    public void registerObserver(Observer obs) {
        _observerList.Add(obs);
    }
    
    private void notify(int maschineId) {
        foreach(Observer obs in _observerList) {
            obs.update(maschineId);
        }
    }
}
   
public class Observer {
    public void update(int maschineId) {
        DateTime localDate = DateTime.Now;
        Console.WriteLine($"Defect bulb identified on maschine {maschineId} at {localDate}.");
    }
}

为什么加await后程序“不正常”

你的startMaschine方法内部,用Task.Run启动了一个需要运行约5小时的任务(10000个灯泡×2秒/个)。当你在prod.startMaschine(maschineID);前加await时,主线程会暂停在这个位置,直到整个生产任务完全结束——这期间控制台会卡死,无法处理用户的任何新输入(比如再启动一台机器、输入2退出),所以你会觉得程序“无法正常运行”。

何时该用await

  • 需要等待任务完成后再执行后续逻辑:比如你的需求是“启动一台机器,必须等它生产完所有灯泡才能启动下一台”,或者需要获取生产任务的结果(比如统计次品总数),这时候必须加await,确保前序任务完成后再走下一步。
  • 需要捕获异步任务的异常:如果异步任务可能抛出异常,不加await的话,未处理的异常会在后台线程触发,可能直接导致程序崩溃;加await后可以用try-catch捕获并处理异常。

何时不该用await

  • 需要任务后台运行,主线程继续处理其他工作:就像你的场景,启动生产机器后,希望用户还能继续操作命令行(启动新机器、退出程序),这时候不能加await,让生产任务在后台线程独立执行即可。

你的代码优化建议

  1. Random实例问题:如果快速连续启动多台机器,每个startMaschine里的Random会用当前时间作为种子,可能生成完全相同的随机数序列,导致次品率不符合预期。建议把Random设为Production类的静态成员:
private static Random _rndGenerator = new Random();

在startMaschine里直接用这个静态实例,避免重复初始化。

  1. 未处理的任务异常:不加await时,startMaschine返回的任务如果抛出异常,会触发UnobservedTaskException,可能导致程序终止。可以在启动任务时添加异常处理:
_ = prod.startMaschine(maschineID).ContinueWith(task => {
    if (task.Exception != null) {
        Console.WriteLine($"机器{maschineID}生产出错:{task.Exception.Message}");
    }
}, TaskContinuationOptions.OnlyOnFaulted);
  1. Main方法调用问题:当前代码里直接调用Main();,但Main是async Task类型,在C# 7.1及以上版本,async Main可以直接作为程序入口,编译器会自动处理,所以可以去掉开头的Main();调用。

内容的提问来源于stack exchange,提问作者Z.J

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:32:26