I'm trying to create a simple asynchronous logger. The idea to make the logging calls non-blocking and as unobtrusive as possible. Please consider the following simplified codes -
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();
}
}
It can be used it as follows (not awaiting on any Log(...) call) -
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");
}
}
My questions are -
There are multiple async
Log(...)
calls one after another. Can the compiler potentially choose to run all them in parallel simultaneously? If yes, does the compiler know to maintain the order of these calls so thatlogger.Log("CreateAccount Validation Start");
doesn't end up running beforelogger.Log("CreateAccount Start");
?If the compiler doesn't preserve order, then is there a way around it other than maintaining a queue within the Logger class?
UPDATE: A clarification - my main concern is avoiding race conditions that could, for example, result in logger.Log("CreateAccount Validation Start");
running/completing before logger.Log("CreateAccount Start");
and calling Log
without blocking CreateAccount
.