异步调用的顺序是否在 .NET 中维护?使用异步实现记录器等待



我正在尝试创建一个简单的异步记录器。使日志记录调用不受阻塞且尽可能不引人注目的想法。请考虑以下简化代码 -

class Logger {
    public async void Log(string message) {
        LogTable log = new LogTable(); //LogTable is an SqlServer table
        log.Timestamp = DateTime.Now;
        log.Message = message;
        log.SomeProp = SomeVariableTimeCalculation();
        var db = new Entities(); //db is an EF6 context
        db.Entry(log).State = EntityState.Added;
        db.LogTables.Add(log);
        await db.SaveChangesAsync();
   }
}    

它可以按如下方式使用它(不等待任何 Log(...) 调用) -

class Account
    private readonly Logger logger = new Logger();
    public void CreateAccount(Account acc) {
        logger.Log("CreateAccount Start");
        //Maybe some async operations here
        logger.Log("CreateAccount Validation Start");
        bool isValid = Validate(acc);
        logger.Log("CreateAccount Validation End");
        if(isValid) {
            logger.Log("CreateAccount Save Start");
            acc.Save();
            logger.Log("CreateAccount Save End");
        }
        else {
            logger.Log("Account validation failed");
        }
        logger.Log("CreateAccount End");
    }
}

我的问题是——

  1. 有多个异步Log(...)调用接连出现。编译器是否可以选择同时并行运行所有这些?如果是,编译器是否知道维护这些调用的顺序,以便logger.Log("CreateAccount Validation Start");不会在logger.Log("CreateAccount Start");之前运行?

  2. 如果编译器不保留顺序,那么除了在 Logger 类中维护队列之外,还有没有办法解决它?

更新:澄清 - 我主要关心的是避免竞争条件,例如,可能导致logger.Log("CreateAccount Validation Start");logger.Log("CreateAccount Start");之前运行/完成,并在不阻止CreateAccount的情况下调用Log

编译器是否可以选择同时并行运行所有这些?

不。异步与并行完全不同。

如果编译器不保留顺序,那么除了在 Logger 类中维护队列之外,还有没有办法解决它?

编译器确实保留顺序(即,await用于顺序异步代码)。但是,队列仍然不是一个坏主意,因为您可能不希望在每次日志记录调用时都命中实际数据库。

除非任何其他

显式使用任务/线程/并行性,否则async方法始终从其调用方的角度同步运行,直到它到达第一个await 1

因此,您Log呼叫至少在等待SaveChangesAsync完成之前无法返回。


1但是,如果相关可等待项已经完成,则此时它可能会继续同步运行。因此,这是它可能将控制权返回给调用方的最早点,而不是保证的控制权返回点。

我认为您本质上要问的是这是否会输出 1、2、3、...、999、1000

for (int i = 1; i <= 1000; ++i)
{
    logger.Log(i.ToString());
}

简单的答案是否定的。 与其他任务相比,每个任务可能而且可能经常需要略有不同的持续时间,因此例如,5 的任务可以在 4 的任务完成之前执行。

最新更新