簡體   English   中英

使用C#4.6.1了解異步方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM