C# 异步调用的顺序是否在.NET中维护?使用异步等待实现记录器?
我正在尝试创建一个简单的异步记录器。使日志调用无阻塞且尽可能不引人注目的想法。请考虑以下简化代码-C# 异步调用的顺序是否在.NET中维护?使用异步等待实现记录器?,c#,async-await,C#,Async Await,我正在尝试创建一个简单的异步记录器。使日志调用无阻塞且尽可能不引人注目的想法。请考虑以下简化代码- class Logger { public async void Log(string message) { LogTable log = new LogTable(); //LogTable is an SqlServer table log.Timestamp = DateTime.Now; log.Message = message;
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(…)
调用,一个接一个。编译器是否可以选择同时并行运行所有它们?如果是,编译器是否知道维护这些调用的顺序,以便logger.Log(“CreateCount Validation Start”)代码>不会在logger.Log(“CreateCount启动”)之前运行代码>
更新:澄清-我主要关心的是避免可能导致
logger.Log(“CreateCount验证启动”)的竞争条件代码>在logger.Log(“CreateCount启动”)之前运行/完成
并调用Log
而不阻塞CreateAccount
除非任何其他明确使用任务/线程/并行,异步
方法始终从调用方的角度同步运行,直到它到达第一个等待
1
因此,至少在调用等待savechangesync
完成之前,Log
调用无法返回
1但是,如果等待的问题已经完成,则此时它可能会继续同步运行。所以这是它可以将控制返回给调用方的最早点,而不是保证返回控制的点
编译器是否可以选择同时并行运行所有它们
不。异步与并行完全不同
如果编译器不保留顺序,那么除了在Logger类中维护队列之外,还有其他方法吗
编译器保留顺序(即,await
用于顺序异步代码)。然而,队列仍然是一个不错的主意,因为您可能不想在每次日志调用时访问实际的数据库。我想您本质上要问的是,这是否会输出1、2、3、…、999、1000
for (int i = 1; i <= 1000; ++i)
{
logger.Log(i.ToString());
}
for(int i=1;i@AlGoreRhythm.Entity框架不支持对数据库的多个并发调用(我假设EF基于savechangesync()
方法)。如果这些调用并行运行,您将得到一个异常。@ErikPhilips单个上下文无法执行并发调用。代码为每个调用创建一个新上下文。不同的上下文都可以同时执行操作。@Servy是的,我没有那么明确。这更多的是关于在这些c语言下小心的注释条件。看起来您希望有两个不相关的执行流,其中每个流将在其自身内保持严格的顺序,但一个流的任何命令是在另一个流的任何命令之前还是之后执行都无关紧要。这与async/await
并不完全相关。您可能希望显式创建某种类型的执行流后台工作程序和对它的日志后处理请求。但是如果日志进入savechangesync
,然后一个后续日志启动,一直到最后,并在第一个日志完成保存之前保存,它们仍然会遇到争用条件。可能不太可能,但可能。@Servy-同意-但希望不会出现争用情况o这里有很多问题,因为时间戳是在保存之前显式获取的。因此,如果它不产生实际错误,那么应该可以根据保存的数据对日志消息进行正确排序。重点是,可以在具有较早时间戳的条目之前将具有较晚时间戳的日志条目添加到字典中。这就是在问题询问时,它可能会发生。谢谢Servy,是的,避免竞争条件是问题的目的。我想我会编辑它以使其清楚。谢谢。我想我应该重新表述这个问题。我不是要比较异步和并行。当你说编译器保留ansyc调用的顺序时,它知道运行t吗在前一个异步调用完成后,是否会执行后续的异步调用?只要您等待前一个异步调用,它们将按顺序运行。@LasseV.Karlsen是的,但这将无法达到目的。我基本上是尝试这样做,以便Log
调用按顺序异步运行,但不会阻止CreateAccount
方法d、 @Achilles那么我是对的。虽然并行性和异步性是不同的,但OP的特定异步代码涉及一定量的并行性,所以说这里没有并行性是完全错误的。(这些操作无法完全并行运行,但实际上,代码也不会完全按顺序运行。)
for (int i = 1; i <= 1000; ++i)
{
logger.Log(i.ToString());
}