【问题标题】:Does this modification makes my method run asynchronously此修改是否使我的方法异步运行
【发布时间】:2016-04-01 02:55:42
【问题描述】:

以下是记录器调用,即阻塞:

public static void Info(Category category, SubLevel subLevel, object message)
{
    CommonLogger?.Info($"{category}, {(int) subLevel}, {message}");
}

我想让它异步执行,因此我做了以下修改,因为根据我的理解,将 Async-Await 用于 void 返回方法,就像当前的那样不是一个好策略:

public static void InfoAsync(Category category, SubLevel subLevel, object message)
{
    Task.Run(() => CommonLogger?.Info($"{category}, {(int)subLevel}, {message}"));
}

代码上下文-

  • 使日志记录异步运行
  • 一劳永逸,主要业务逻辑分开进行

我的问题是:

  1. 我做出此更改是否正确?

  2. 还有更好的方法吗?

【问题讨论】:

  • 就回答标题中的问题而言 - 是的,它现在将异步运行。其他 2 个问题过于主观,可能是基于意见的。改为在 codereview.stackexchange.com 上获取它。无论是在 SO 还是 codereview 上,都需要更多的上下文。
  • 感谢我将发布到 CodeReview
  • 我做这个改变是否正确取决于你想要达到的目标。 还有更好的方法,做同样的事情取决于你想要达到的目标。
  • 要发布代码审查,您需要更多详细信息。
  • 此上下文是否有助于获得更好的视图

标签: c# asynchronous async-await task-parallel-library


【解决方案1】:

此修改是否使我的方法异步运行?

不,它没有。 Concurrency and parallelism are two different concepts。人们倾向于使并发和并行可互换,但实际上并非如此。您的代码将与其他执行单元并行运行,但操作本身并不是异步。如果你真的想进行异步操作,你可以使用异步 IO 来写入底层记录器。

我进行此更改是否正确?

我会说。这称为async over sync 反模式(有关其含义的详细说明,请参阅链接)。我会避免这种模式,因为它会产生一种错误的异步感。你的方法并不是真正的自然异步,true asynchronous methods don't need to use extra thread-pool threads

还有更好的方法吗?

是的,不要这样做。让该方法的调用者显式调用Task.Run,以便他们知道所述委托将在线程池上执行。或者更好的是,将 async IO 与记录器实现一起使用。毕竟,我假设这可能会写入底层文件或执行某种网络操作以通过网络发送日志。如果是这样,请改用真正的异步 API。

【讨论】:

  • 您的意思是直接使用Task.Run调用同步版本,例如:Task.Run(() => Info());
  • @MrinalKamboj 是的。
  • @JᴀʏMᴇᴇ 不,在线程池线程上排队委托没有任何“异步”。随意详细说明为什么我的答案很糟糕,也许我可以改进它。
  • @MrinalKamboj 你可以使用async appenders 登录log4net。
  • 我完全同意将这个方法隐藏在 Task.Run() 下但不让调用者轻易知道是一种反模式。为了增加讨论,如果在 ASP.NET 上下文中调用它,您实际上会通过占用一个额外的线程来记录可能接受传入请求的内容,从而降低应用程序的可伸缩性。如果您希望它是异步的,请一直使用异步以最大程度地利用它。
【解决方案2】:

是的,这现在是一种异步方法,但是,其他两个不是正确的问题(正如 JayMee 所提到的)。它们纯粹是人们发展的方式。例如,我会这样做,但 Joe Bloggs 可能不会。

希望这会有所帮助。

【讨论】:

  • 请乔博客链接
  • 如果 Stack Overflow 上有 Joe Bloggs,我会感到非常惊讶 :-)。这只是一个上下文名称,类似于 Joe Contoso。
  • SO 上有 16 个 Joe Bloggs,还有一个 Not Joe Bloggs。阿托。
  • 所有这些都是私人的,没有声誉,没有头像,也没有活动......该死的那些用垃圾填满互联网的人:-/
【解决方案3】:
  1. 是的,现在 异步运行(在某种意义上,您的方法在不等待日志记录完成的情况下返回,而不是 Yuval Itzchakov 解释的含义)。
  2. 那么,您为什么不想更改该方法以返回 Task 并使其也可供调用者等待:

    public static async Task InfoAsync(Category category, SubLevel subLevel, object message)
    {
        await Task.Run(() => CommonLogger?.Info($"{category}, {(int)subLevel}, {message}"));
    }
    

但正如您和其他评论者指出的那样:如果您不需要这个,它只会增加不必要的复杂性(例如,编译器会构建一个不必要的状态机)。

一般来说,要回答“能否做得更好”之类的问题,需要了解“更好”的标准。这取决于如何以及在哪些条件下会调用它以及要求是什么。

【讨论】:

  • 为什么要添加异步等待?这似乎没有任何好处,并使执行更加复杂?
  • 它对我来说就是一劳永逸,我没有理由返回任务,它只是在后台记录详细信息
  • @Liam 好吧,这就是关于“会不会更好”的问题。我怎么知道那里有什么要求。据我所知,使其异步没有任何缺点,那么为什么不向调用者提供这种可能性呢?
  • 让它异步没有任何缺点是的,它确实使执行(由 CLR 执行)变得更加复杂和昂贵。如果 Op 只是想开火而忘记,这只会使其运行速度变慢而没有任何好处
  • @MrinalKamboj 我实际上也是指async 版本:) ....我想关于这个小问题的讨论已经够多了。
猜你喜欢
  • 2015-07-07
  • 1970-01-01
  • 2023-03-16
  • 2021-04-15
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多