在C#中使用async而不等待?

29 c# task-parallel-library async-await c#-5.0

考虑在没有等待的情况下使用async.

想想也许你误解了异步的作用.警告是完全正确的:如果您将方法标记为异步但不在任何地方使用等待,那么您的方法将不是异步的.如果调用它,方法中的所有代码将同步执行.

我想编写一个应该运行异步但不需要使用await的方法.例如,当使用线程时

public async Task PushCallAsync(CallNotificationInfo callNotificationInfo)
{
    Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId,
}
Run Code Online (Sandbox Code Playgroud)

我想要调用PushCallAsync并运行异步,不想使用等待.

我可以在C#中使用async而无需等待吗?

Vis*_*ons 29

如果您Logger.LogInfo已经异步,这就足够了:

public void PushCallAsync(CallNotificationInfo callNotificationInfo)
{
    Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId,
}
Run Code Online (Sandbox Code Playgroud)

如果它不是在不等待它的情况下启动异步

public void PushCallAsync(CallNotificationInfo callNotificationInfo)
{
    Task.Run(() => Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId));
}
Run Code Online (Sandbox Code Playgroud)

  • 不."Task.Run"使用不同的默认值:`DenyChildAttach`和`TaskScheduler.Default`.`TaskScheduler`特别重要,因为默认情况下`StartNew`将使用`TaskScheduler.Current`,这使得它根据调用者的上下文以不同方式调度委托.这让很多人惹恼了许多团队采用的代码规则永远不会允许`StartNew`,除非指定了`TaskScheduler`. (7认同)
  • 按照惯例,除非它具有"async"关键字,否则不应将方法命名为"Async". (5认同)
  • 您应该使用`Task.Run`而不是`Task.Factory.StartNew`来执行等待任务.[这就是原因](http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx). (3认同)

Ste*_*ary 24

你仍然是误解async.该async关键字并不会意味着"另一个线程上运行".

要将一些代码推送到另一个线程,您需要明确地执行此操作,例如Task.Run:

await Task.Run(() => Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId));
Run Code Online (Sandbox Code Playgroud)

我有一个async/ await介绍帖子,你可能会发现有用.


Rob*_*tto 6

你误会了async。实际上,它只是告诉编译器在后台为您传播控制流的反转。这样整个方法栈都被标记为异步。

您实际要做什么取决于您的问题。(让我们考虑您的调用Logger.LogInfo(..)是一个async方法,因为它最终会调用File.WriteAsync()左右。

  • 如果调用函数是一个无效的事件处理程序,那很好。异步调用将在后台某种程度上发生(即File.WriteAsync)。您不希望控制流有任何结果。那是火,忘了。
  • 但是,如果您想对结果进行任何操作,或者仅想继续Logger.LogInfo(..)进行操作,则必须采取预防措施。当您的方法以某种方式位于调用堆栈的中间时,就是这种情况。然后Logger.LogInfo(..)通常会返回Task,您可以等待。但是要小心调用task.Wait(),因为它将死锁您的GUI线程。而是使用await或返回Task(然后您可以忽略异步):

public void PushCallAsync(CallNotificationInfo callNotificationInfo) 
{
   return Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId); 
}
Run Code Online (Sandbox Code Playgroud)

要么

 public async void PushCallAsync(CallNotificationInfo callNotificationInfo) 
 {
    await Logger.LogInfo("Pushing new call {0} with {1} id".Fill(callNotificationInfo.CallerId); 
 }
Run Code Online (Sandbox Code Playgroud)

  • 除非它是事件处理程序,否则不应使用“异步无效”。那是唯一可接受的时间,也是制作异步事件处理程序的唯一正确方法。如果您的同步方法是“无效”,则应该是“异步任务”。这是由于异常处理,事件处理程序将抛出“ SynchronizationContext”(类似于同步事件)而不是调用者。如果可能的话,异步事件处理程序应该是一个薄的私有包装器,一个“异步任务”函数(以便可以对其进行测试或重新使用)。 (4认同)