【发布时间】:2020-05-15 13:26:58
【问题描述】:
等待发送非必要指标对我来说毫无意义,因为它会在每次调用后端 dotnet 核心服务时增加延迟(等待服务器的响应),每次客户端调用可能会发生多次.尽管如此,在失败时记录错误很重要(不过我不需要抛出它,因为指标的失败不应该影响服务)。
我发现了多种方法。以下是以 FireAndForget 方式调用的方法:
public async Task FireAndForget()
{
try{ await sendTheMetric(); } // Try catch on the await, to log exceptions
catch(Exception e){ logger.debug(e) }
}
方法一:去掉await。
FireAndForget(); // No await in front of the call
方法 2:对我来说似乎类似于方法 1,因为我们不等待 Task.Factory.StartNew 调用。
Task.Factory.StartNew(async () => await MyAsyncTask());
方法 3:作为工作项在 ThreadPool 上排队。
ThreadPool.QueueUserWorkItem(async o => await FireAndForget());
我很难找到应该将哪个用于 Fire 并忘记调用来发送非必要指标。我的目标是在每次发送指标时不增加对我的服务的每次调用的延迟。当度量标准发送失败时记录错误很重要,但它永远不应该重新抛出。线程上下文对于任务的执行并不重要。任务应该总是,或者至少几乎总是,被完成。
哪一项是满足需求的最佳实践?还是都一样?
注意:我没有包含async void,因为它看起来有风险(如果发生异常,它可能会崩溃,因为没有任务会包装它)。
【问题讨论】:
-
我会使用
LoggingService将您的指标缓存在队列中,立即返回您的业务逻辑,并在后台的工作线程中干净地处理它们(所以当出现问题时,您可以处理它完全封装在一个中心点)。但恐怕你的问题没有明确的答案,而且非常基于意见。 -
我认为“写日志”不应该在线程池中排队。它应该始终按照它的生产顺序。就像弗兰兹所说,日志服务应该处理它。 (比如排队)等
-
我通常会等待这些寻找的任务,这样异常就不会落空。否则
UnobservedTaskException会使我的程序崩溃。但是,在您的情况下,您正在任务中捕获异常,因此丢弃它是有意义的。但是当您记录到文件并希望它是线程安全的时,您必须等待任务,捕获异常并记录它 -
如何将 Func
添加到 BlockingCollection 中,然后由单独的线程读取并处理?
标签: c# asynchronous .net-core async-await fire-and-forget