C# 启动和异步fire and forget调用的正确方法?

C# 启动和异步fire and forget调用的正确方法?,c#,.net,.net-core,async-await,task-parallel-library,C#,.net,.net Core,Async Await,Task Parallel Library,我有一个异步调用(DoAsyncWork()),我希望以一种先发后忘的方式启动,也就是说,我对它的结果不感兴趣,希望调用线程在异步方法完成之前继续 正确的方法是什么?我在.NET Framework 4.6和.NETCore 2中都需要这个,以防有差异 public async Task<MyResult> DoWorkAsync(){...} public void StarterA(){ Task.Run(() => DoWorkAsync()); } publ

我有一个异步调用(
DoAsyncWork()
),我希望以一种先发后忘的方式启动,也就是说,我对它的结果不感兴趣,希望调用线程在异步方法完成之前继续

正确的方法是什么?我在.NET Framework 4.6和.NETCore 2中都需要这个,以防有差异

public async Task<MyResult> DoWorkAsync(){...}

public void StarterA(){
    Task.Run(() => DoWorkAsync());
}

public void StarterB(){
    Task.Run(async () => await DoWorkAsync());
}

public async Task doworksync(){…}
公共图书馆A({
Task.Run(()=>doworksync());
}
公共图书馆B({
运行(async()=>wait-doworksync());
}
它是这两个中的一个还是其他什么不同/更好的


//编辑:理想情况下不需要任何额外的库。

这取决于您所说的正确:)

例如:您对“fire and forget”调用中抛出的异常感兴趣吗?如果没有,那么这就没问题了。尽管您可能需要考虑的是任务所处的环境

例如,如果这是一个asp.net应用程序,并且您在由于调用.aspx或.svc而实例化的线程的生存期内执行此操作。该任务成为该(前台)线程的后台线程。前台线程可能在“触发并忘记”任务完成之前被应用程序池清除

因此,还要考虑任务所在的线程

我认为本文为您提供了一些有用的信息:

还请注意,如果在任务中不返回值,任务将不会返回异常信息。来源是微软考试参考书70-483 在网上某个地方可能有免费的版本;P

如果您有一个异步方法被一个非异步方法调用,并且您希望知道它的结果,那么了解它可能是有用的。您可以使用.GetAwaiter().GetResult()

另外,我认为注意异步和多线程之间的区别很重要

只有当操作使用计算机的其他部分而不是CPU时,异步才有用。比如网络或I/O操作。然后使用async告诉系统继续并在其他地方使用CPU电源,而不是仅仅为了等待响应而“阻塞”CPU中的线程

多线程是CPU中不同线程上的操作分配(例如,创建一个创建前台线程的后台线程的任务…前台线程是构成应用程序的线程,它们是主线程,后台线程链接到前台线程。如果关闭链接的前台线程,后台线程也会关闭) 这允许CPU同时处理不同的任务

如果CPU是4线程CPU,将这两者结合起来可以确保CPU不会被阻塞在4个线程上。但是,当它等待等待I/O操作的异步任务时,可以打开更多线程

我希望这能为您提供所需的信息,无论您在做什么:)

正确的方法是什么

首先,你需要决定你是否真的想要。根据我的经验,约有90%的人要求这样做,但实际上他们不想要火和遗忘;他们需要后台处理服务

具体而言,火灾和遗忘意味着:

  • 您不在乎操作何时完成
  • 您不在乎在执行操作时是否存在任何异常
  • 你根本不在乎动作是否完成
  • 因此,fire and forget的实际用例小得惊人。像更新服务器端缓存这样的操作就可以了。发送电子邮件、生成文档或任何与业务相关的操作都是不正常的,因为您(1)希望操作完成,并且(2)在操作出错时收到通知

    绝大多数时候,人们根本不想要火和遗忘;他们需要后台处理服务。构建其中一个队列的正确方法是添加一个可靠队列(例如Azure队列/Amazon SQS,甚至一个数据库),并使用一个独立的后台进程(例如Azure Function/Amazon Lambda/.NET Core BackgroundService/Win32 service)处理该队列。这基本上就是Hangfire所提供的(使用数据库作为队列,并在ASP.NET进程的proc中运行后台进程)

    它是这两个中的一个还是其他什么不同/更好的

    在一般情况下。这不是你“默认”想要做的事情


    然而,在这个特定的情况下,
    async
    lambda只调用一个方法,省略
    async
    wait
    就可以了。

    你听说过hang fire吗?@EhsanSajjad没有。不过,理想情况下,我希望这样做不需要任何额外的lib。感谢您的真知灼见!是的,我对任何异常都不感兴趣(DoWorkAsync中有异常处理)。是的,所有这些都在ASP.NET应用程序中。这会改变你的答案吗?不会,你可以跳过关于返回值的部分。这是不必要的:)但我想强调的部分,背景线程在前景线程。我的公司决定在aspx页面的线程生命周期内使用fire and forget方法对azure application insights进行额外调用。并惊讶地发现分配没有被记录。这是因为任务是在该页面的操作结束之前实例化的。这意味着线程和刚刚创建的任务都被应用程序池清除了。请看我在上面的链接,谢谢。对于ASP.NET部分,我将使用来自Scotts Post的queuebackgroundworkitem感谢您的回答!事实上,我的案例就是您提到的ok:更新缓存;)