【问题标题】:What to deal with multiple asynchronous method invocations in C#在 C# 中如何处理多个异步方法调用
【发布时间】:2019-05-12 15:23:32
【问题描述】:

假设,我有一个简单的类,里面有异步方法:

public class Writer
{
    public Task WriteAsync(string message);
}

这是内部类,对于应用程序的业务逻辑来说绝对可以忽略不计。

方法的主要思想,就是当它被调用时——方法必须立即将控制权交还给调用方法,避免在重要的、充满业务逻辑的调用方法中出现任何可能的延迟(延迟为当然可以调用该方法)。

这个方法经常在不同的地方调用。我们并不关心它是否成功,或者在出现意外情况时不会写最后一条消息。没关系。

所以,问题是,我怎样才能调用WriteAsync 以避免调用方法中可能出现的任何延迟

我想过Task.Run(() => WriteAsync(message))(没有await!我们不需要等待这个!),但这不会让我的线程池充满大量无用的工作吗?而且到处写这样的代码是相当繁重的......

【问题讨论】:

  • 如果方法的作用是无用的,如果方法成功与否都无关紧要......为什么要拥有它?
  • 从这个意义上说,任务非常轻,除非实现本身很重,如果您关心如何触发和忘记任务,只需创建一个运行 Task.Run(() 的 void 方法=> WriteAsync(message))...,但是就像大卫说的那样,如果那个主线程被终止,任务就会被终止,那么,你真的需要这个吗?
  • 如果它真的“无用”,那么就不要这样做:) 但是如果你想让它运行,那么你别无选择,只能花费处理能力去做。您想要的通常称为“一劳永逸”(在后台运行并忽略它)。请记住a Task doesn't necessarily run on its own thread,尽管它可能会。
  • @David 这是一个特殊的方法,最初是给InfluxDb添加指标,只是一个简单的例子。

标签: c# multithreading task threadpool


【解决方案1】:

因为该方法是异步的,所以根据定义,它已经立即将控制权返回给调用者。如果该方法的实现实际上不是异步的,那么它不应该返回Task,名称中不包含Async,并让调用者清楚它是同步的,或者它应该修复其实现中的错误,使其长时间阻塞调用者。该方法的调用者理所当然地期望,作为一个异步方法,它会通过正常调用该方法立即将控制权返回给调用者。如果该方法中存在使其无法执行此操作的错误,则您不应解决该错误,并让调用者在声称不是同步方法时将其视为同步方法。

【讨论】:

  • 抱歉我的不理解,但是如果实现是同步的,但是耗时耗资源怎么办?你可能会说我们应该使用Task.Run,这很好,这就是我想要避免的,用无用的线程乱扔我的线程池。
  • @YuriiN。如果方法是同步的,那么为什么它返回一个Task,为什么它的名称中有Async?如果它是同步的,并且不能设为异步,那么它不应返回 Task 并且不应以其名称声称是异步的
  • 它可以是异步的...除了第一个同步部分(即准备写入数据)可能需要 10 秒,然后适当的await 执行异步部分(即写入数据库).. .
  • @AlexeiLevenkov 那么它实际上不是一个异步方法。它不应该在标记为异步的方法中进行耗时的同步工作。如果它有耗时的同步工作,它应该在线程池线程中运行,而不是在声称是异步的方法中同步执行,并强制该方法的每个调用者解决该错误。
【解决方案2】:

您可以将写入排队并处理队列,即在专用后台线程上执行写入。这就是当您调用Task.Run 时会发生的情况,即您在线程池中将委托排队。如果您需要更多控制权,例如可以使用BlockingCollection<T>

有一个示例说明如何使用BlockingCollection<T> 读取和写入MSDN 上同时可用的项目。

使用这种方法,调用WriteAsync 只会阻塞将消息添加到队列所需的时间,这个时间应该可以忽略不计。

【讨论】:

  • 感谢您的回答,这正是我所需要的。
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 2019-10-16
  • 2011-03-18
  • 2018-11-10
  • 1970-01-01
  • 2020-11-09
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多