[英]Understanding Async Methods using C# 4.6.1
我有以下同步方法
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));
}
這不會插入任何內容。 這是為什么?
首先,我將嘗試避免使async void InfoAsync
。
優先使用異步Task方法而不是異步void方法
相反,您應該嘗試這樣的事情:
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
。 在此處了解更多信息。 它只會增加開銷,並且可能會對性能產生負面影響。 其次,由於您返回一個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.
}
如果必須在WebAPP的任何其他方法(不是異步方法)中使用此Log.InfoAsync怎么辦?
然后,他們應該使用Info
而不是InfoAsync
。 如果可能,請嘗試完全使用async
。 如果不可能,則應考慮是否確實使用async
方法添加了任何內容。 當您await
它時,您仍然會阻塞線程,如果您使用的是.Result
則有可能出現死鎖 。 因此,在我看來,實際上很少有情況需要在同步上下文中使用async
方法。
進一步有趣的讀物: 是否應棄用Task.Wait?
因為您的應用程序在記錄器完成之前就終止了。
您只需await
呼叫:
static void Main(string[] args)
{
//Log.Info("Synchronous write");
await Log.InfoAsync(DateTime.Now.ToString(CultureInfo.InvariantCulture));
}
或者,因為這在Main
不起作用,請閱讀: 無法在控制台應用程序的“ Main”方法上指定“ async”修飾符
您可以簡單地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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.