Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用“Task.Run”或不使用“await”调用异步方法,触发并忘记`_C# - Fatal编程技术网

C# 使用“Task.Run”或不使用“await”调用异步方法,触发并忘记`

C# 使用“Task.Run”或不使用“await”调用异步方法,触发并忘记`,c#,C#,注意:这是一个不属于Asp.Net和web应用领域的问题 一般来说,尤其是当涉及到库或控制台应用程序时,为了启动并忘记异步方法,是否最好只调用异步方法而不等待它或使用任务运行 基本上: public static void Main(){ // Doing _ = DoSomethingAsync(); // vs. _ = Task.Run(DoSomethingAsync); } private static async Task DoSomethingAsync()

注意:这是一个不属于Asp.Net和web应用领域的问题

一般来说,尤其是当涉及到库或控制台应用程序时,为了启动并忘记异步方法,是否最好只调用异步方法而不等待它或使用任务运行

基本上:

public static void Main(){
  // Doing
  _ = DoSomethingAsync();

  // vs.
  _ = Task.Run(DoSomethingAsync);
}

private static async Task DoSomethingAsync()
 {
   ...
 }


一般来说,这取决于任务。运行是更安全的选择,它背后的推理取决于两件事:

  • 如果我们能保证
    async
    方法总是异步的。对于库项目或异步方法位于调用方不管理的代码中,保证方法始终是异步的可能变得特别棘手。例如,一旦我在库中实现了类似于此示例的方法:
  • 这实际上会使
    onmessagentification
    同步操作,并且必须等待
    DoSlowOperation()
    完成。因此,为了避免修复问题,我不得不将其更改为:

      _ = Task.Run(onMessageNotification);
      _ = MakePizzaAsync();
    
  • 在第一次
    wait
    操作之前,异步方法中不会有长时间运行的操作。调用者可能导致问题的另一种方式是,如果
    onMsgnotification
    Func是通过以下方式实现的:
  • Func onMsgNotification=async()=>{
    DoSlowOperation();
    等待异步操作();
    }
    
    这仍然会减慢
    HandleMessages
    方法的速度,因为
    DoSlowOperation
    仍在同步调用

    一般来说,尤其是当涉及到库或控制台应用程序时,为了触发并忘记异步方法,最好是在不等待异步方法的情况下调用它,或者使用Task.Run

    一般来说,最好不要用火,不要忘记

    “开火并忘记”是指:

  • 你不在乎代码是否有异常。任何异常都会导致它无声地失败;没有日志记录、没有通知等
  • 您不需要知道代码何时完成。也就是说,消费应用程序永远不需要等待代码完成。即使在关机期间
  • 您不需要代码来完成。作为(2)的推论,fire-and-forget代码可能无法运行到完成;作为(1)的推论,您将不会收到它未能完成的通知
  • 简言之,“开火并忘记”只适用于极少数任务。例如,更新缓存。我想说大概85%或更多的“fire and forget”代码是错误的——它使用fire and forget作为不应该是fire and forget的代码

    所以我想说最好的解决办法是不要用火和遗忘。至少,您应该在某个地方公开一个表示“后续操作”的
    任务。考虑将<代码>任务<代码>添加到您的返回类型中,或者将其作为属性公开。

    特别是在图书馆里,采用“火与忘”意味着你迫使所有的消费者永远不知道什么时候关闭和退出是安全的。但是,如果你真的想做的火和忘记,有几个选择

    A.一个选项是调用
    异步void
    函数。消费应用程序仍然无法确定代码是否/何时完成,但至少在这种情况下不会忽略异常

    B.另一种选择是在没有上下文的情况下启动任务。此选项具有激发和忘记代码的两个缺点:异常被忽略,调用代码无法知道何时完成

    这两个建议都是在没有上下文的情况下启动任务的。有,或者您可以在
    任务中包装调用。运行
    (效率稍低,但工作正常)

    我不建议直接开始这项任务。虽然这在控制台应用程序中可以正常工作,但它不适合在提供上下文的情况下调用库

    Func<Task> onMsgNotification = () => {
      DoSlowOperation();
      return Task.CompletedTask;
    }
    
      _ = Task.Run(onMessageNotification);
      _ = MakePizzaAsync();
    
    Func<Task> onMsgNotification = async () => {
      DoSlowOperation();
      await AsyncOperation();
    }