使用C#4.6.1了解异步方法

时间:2016-08-12 07:37:46

标签: c# mongodb c#-4.0 asynchronous

我有以下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));
        }

这将不会插入任何内容。那是为什么?

2 个答案:

答案 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)