我有以下Synchronous和异步方法
public static void Info(string message)
{
if (_logTypes.Contains(InfoLogType))
{
string applicationName, methodName, className;
ReflectClassAndMethod(out applicationName, out className, out methodName);
Write(applicationName, "Info", className, methodName, message);
}
}
public static async void InfoAsync(string message)
{
if (_logTypes.Contains(InfoLogType))
{
string applicationName, methodName, className;
ReflectClassAndMethod(out applicationName, out className, out methodName);
await WriteAsync(applicationName, "Info", className, methodName, message);
}
}
此外,我的写作方法是这样的:
private static void Write(string applicationName, string logType, string className, string methodName, string message)
{
// construct me _event object
var collection = Database.GetCollection<Event>(typeof(Event).Name);
collection.InsertOne(_event);
}
private static Task WriteAsync(string applicationName, string logType, string className, string methodName, string message)
{
// construct my _event object
var collection = Database.GetCollection<Event>(typeof(Event).Name);
await collection.InsertOneAsync(_event);
}
使用测试控制台应用程序我将这些同步和异步方法称为:
static void Main(string[] args)
{
Log.Info("Synchronous write");
Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture));
}
这将在我的Mongo Collection中插入两个文档。但如果我评论同步呼叫,则不会插入任何内容。
static void Main(string[] args)
{
//Log.Info("Synchronous write");
Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture));
}
这将不会插入任何内容。那是为什么?
答案 0 :(得分:3)
首先,我会尝试avoid async void InfoAsync
。
首选异步空方法
上的异步任务方法
相反,你应该尝试这样的事情:
public static Task InfoAsync(string message)
{
if (_logTypes.Contains(InfoLogType))
{
string applicationName, methodName, className;
ReflectClassAndMethod(out applicationName, out className, out methodName);
return WriteAsync(applicationName, "Info", className, methodName, message);
}
}
这有几个好处。首先,没有理由等待WriteAsync
。阅读更多相关信息here。它只会增加开销,并可能会对性能产生负面影响。其次,因为您返回Task
而不是void
,所以调用者可以正常等待它。
而await
在你的主要代替。由于它是主要的,因此您无法使用await
,而是可以使用WaitAndUnwrapException()。
static void Main(string[] args)
{
//Log.Info("Synchronous write");
var task = Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture));
task.WaitAndUnwrapException();
// or
// task.Wait();
// Now the application won't finish before the async method is done.
}
如果我必须在我的任何其他方法中使用此Log.InfoAsync,该怎么办? WebAPP,哪些不是异步方法?
然后他们应该使用Info
而不是InfoAsync
。如果可能,请尝试一直使用async
。如果不可能,那么您应该考虑是否真的使用async
方法添加任何内容。当你await
时,你仍会阻止该帖子,如果你正在使用.Result
there's a chance of deadlock。所以,在我看来,当你想在同步上下文中使用async
方法的情况很少时。
进一步有趣的阅读:Should Task.Wait be deprecated?
答案 1 :(得分:2)
因为您的应用程序在记录器完成之前终止。
您只需await
来电:
static void Main(string[] args)
{
//Log.Info("Synchronous write");
await Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture));
}
或者,因为这在Main
中不起作用,请阅读:Can't specify the 'async' modifier on the 'Main' method of a console app
您可以简单地Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture)).Wait();
修改强>:
使用C#7.1时, async Main
现已可用:https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.1/async-main.md
所以只需使用static async Task Main(string[] args)