以下是记录器调用,即阻塞:
public static void Info(Category category, SubLevel subLevel, object message)
{
CommonLogger?.Info($"{category}, {(int) subLevel}, {message}");
}
我想让它成为异步执行,因此我做了以下修改,因为根据我的理解,使用Async-Await for void return方法,就像当前的一个不是一个好的策略:
public static void InfoAsync(Category category, SubLevel subLevel, object message)
{
Task.Run(() => CommonLogger?.Info($"{category}, {(int)subLevel}, {message}"));
}
代码上下文 -
我的问题是:
我做出此更改是否正确?
还有更好的方法吗?
答案 0 :(得分:5)
此修改是否使我的方法异步运行?
不,它没有。 Concurrency and parallelism are two different concepts。人们倾向于使并发和并行可互换,但他们确实不是。您的代码将在 parallel 中运行到其他执行单元,但操作本身并非异步。如果您真的想要进行异步操作,那么您可以使用异步IO来写入底层记录器。
我做出此更改是否正确?
我会说没有。这被称为async over sync反模式(请参阅链接以获得对其含义的详尽解释)。我会避免这种模式,因为它会产生错误的异步感。您的方法并非真正自然异步,true asynchronous methods don't need to use extra thread-pool threads。
还有更好的方法吗?
是的,根本不要这样做。让这个方法的调用者显式调用Task.Run
,这样他们就知道所述委托将在线程池上执行。或者甚至更好,使用 async IO 和记录器实现。毕竟,我假设这可能会写入底层文件或执行某种网络操作以通过网络发送日志。如果是这样,请改用真正的异步API。
答案 1 :(得分:1)
那么,为什么你不想改变那个方法来返回Task
并让它等待来电者:
public static async Task InfoAsync(Category category, SubLevel subLevel, object message)
{
await Task.Run(() => CommonLogger?.Info($"{category}, {(int)subLevel}, {message}"));
}
但正如你和其他评论者所指出的那样:如果你不需要这个,它只会增加不必要的复杂性(例如编译器构建一个不必要的状态机)。
一般来说,要回答“能否做得更好”这样的问题,就需要知道“更好”的标准。它取决于 以及在下调用哪些条件以及要求是什么。
答案 2 :(得分:1)
是的,这是一个ASync方法,但是,其他两个都不是正确的问题(如JayMee所述)。它们纯粹是人们如何发展的。例如,我会这样做,但是,Joe Bloggs可能没有。
希望这有帮助。