触发并忘记发送非必要指标的异步方法的最佳实践

Dav*_*d G 6 c# asynchronous fire-and-forget async-await .net-core

等待发送非必要指标对我来说毫无意义,因为它会在每次调用后端 dotnet 核心服务时增加延迟(等待服务器的响应),每次客户端调用可能会发生多次。尽管如此,在失败时记录错误仍然很重要(我不需要抛出它,因为指标的失败不应该影响服务)。

我找到了多种方法。这是以 FireAndForget 方式调用的方法:

public async Task FireAndForget()
{
    try{ await sendTheMetric(); } // Try catch on the await, to log exceptions
    catch(Exception e){ logger.debug(e) }
}
Run Code Online (Sandbox Code Playgroud)

方法一:去掉await。

FireAndForget(); // No await in front of the call
Run Code Online (Sandbox Code Playgroud)

方法 2:对我来说似乎类似于方法 1,因为我们不等待 Task.Factory.StartNew 调用。

Task.Factory.StartNew(async () => await MyAsyncTask());
Run Code Online (Sandbox Code Playgroud)

方法 3:作为工作项在 ThreadPool 上排队。

ThreadPool.QueueUserWorkItem(async o => await FireAndForget());
Run Code Online (Sandbox Code Playgroud)

我很难找到应该将哪个用于 Fire 并忘记调用发送非必要指标。我的目标是在每次发送指标时不增加对我的服务的每次调用的延迟。当指标发送失败时记录错误很重要,但它不应该重新抛出。线程上下文对于任务的执行并不重要。任务应该总是,或至少几乎总是,完成。

哪个是需求的最佳实践?还是他们都一样?

注意:我没有包含async void,因为它看起来有风险(如果发生异常,它可能会崩溃,因为没有 Task 会包装它)。

Pau*_*all 10

希望这不会使水变得浑浊,但有第四种选择(根据我所阅读的内容)正在成为更容易接受的选择。

从 C#7.0 开始,您可以选择对此类实例使用丢弃。

_ = FireAndForget();
Run Code Online (Sandbox Code Playgroud)

这实质上表明不需要该任务,因此不需要返回值。似乎比方法 1 更值得推荐,因为这意味着您明确指出它是“即发即忘”(这不那么模棱两可,看起来不像是编码错误)。

  • 似乎也得到了文档的确认:https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/function/discards#a-standalone-discard (2认同)