C# 使用Async/Await重写我的Utils库的正确方法

C# 使用Async/Await重写我的Utils库的正确方法,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我有很多用于许多不同项目的UTIL类,其中大多数是静态的,由静态方法组成,这些静态方法通常互不调用 我的目的是利用新的async/await特性,但不重写所有内容,因此我的问题是:我是否可以在Task.Run(()=>MethodName)中为每个名为MethodAsync的现有方法添加一个新方法 例如: //old code that will not be removed static void DoSomething() { ... } //new code that will be a

我有很多用于许多不同项目的UTIL类,其中大多数是静态的,由静态方法组成,这些静态方法通常互不调用

我的目的是利用新的async/await特性,但不重写所有内容,因此我的问题是:我是否可以在Task.Run(()=>MethodName)中为每个名为MethodAsync的现有方法添加一个新方法

例如:

//old code that will not be removed
static void DoSomething()
{ ... }

//new code that will be added
static async Task DoSomethingAsync()
{
   //not really sure if Im supposed to use await/async here.
   //isn't Task awaitable even without async??
   return await Task.Run(() => DoSomething());
}
基本上,在旧代码中,我只有一个普通的同步方法,而在新代码中,我有一个异步方法,如果CLR将其视为CPU绑定的方法,它甚至可以在另一个线程中运行

如果我理解正确,根据定义,每个异步方法都包含一个等待对象的等待,该对象是一个任务或另一个异步方法

这意味着每当我可以使用async.NET方法时,我都应该等待它并将调用方方法标记为async

但是,其他不调用任何异步方法但可能需要一些时间才能完成的方法都应该通过Task.Run调用调用

对吧?

编辑

因此,我已经阅读了所有发布的链接、msdn上的最佳实践和一些博客文章,但在使用新的async/await功能进行编码时,我仍然需要一个完整的例程。 到目前为止,我得到的是:

1) 具有异步替代方案的每个.NET方法都应该使用异步替代方案。(据我所知,.NET异步方法只存在于可以异步的方法中)

2) 每个使用异步方法的方法也应该是异步的

3) 每个不使用异步方法(因为不可用)但仍需要一些cpu时间来执行的方法都应该通过使用Task.Run将它们包装为异步(我知道在这种情况下,应该由客户机使用Task.Run,如果他们愿意的话,但由于我只为需要50毫秒以上才能执行的方法添加这些包装,而且仍然可以使用非异步版本的方法,我仍然不明白为什么不将此包装放在库中)

4) 由于等待其他源(如internet、数据库、事件等)而占用非cpu时间的每个方法都应使用TaskFactory.FromAsync或TaskCompletionSource


5) System.Threading.Tasks.Parallel.Invoke(method1、method2等)现在已不推荐使用。从我读到的Task.Run已经运行了并发线程,如果CLR认为需要并发。因此,Task.Run似乎已经在需要时使用了Parallel.Invoke。

这一点在本文中已经讨论过,我认为这是一个糟糕的设计,其原因如下:

例如,考虑一个简单的方法,如
Dictionary.Add(TKey,TValue)
。这是一种非常快速的方法,对吗?通常是的,但请记住字典是如何工作的:它需要对键进行散列,以便找到要将其放入的正确bucket,并且需要检查键与bucket中已有的其他条目是否相等。这些散列和相等性检查可能导致对用户代码的调用,谁知道这些操作会做什么或需要多长时间。字典上的每个方法都应该公开异步包装器吗?这显然是一个极端的例子,但也有更简单的例子,比如正则表达式。提供给Regex的正则表达式模式的复杂性以及输入字符串的性质和大小会对与Regex匹配的运行时间产生重大影响,以至于Regex现在支持可选超时……Regex上的每个方法是否都应该具有异步等价物?我真的希望不是

显然,我建议您也阅读整篇文章,但我希望上面强调了为什么公开
*Async()
方法不应该在库中封装同步方法的一个重要原因


我希望这能有所帮助。

我终于找到了好的资源,消除了我所有的疑虑:

第一个是“基于任务的异步模式”,可在 本文档解释了async/await特性,以及如何/何时使用它,它包含了许多实际示例和我现在在每个项目上使用的一些非常有用的静态方法

第二个是“异步的禅:最佳性能的最佳实践”,可在 这是对异步功能的完整概述,并对并行功能进行了一些介绍,同时也解释了为什么它不应该是使用Task.Run()方法的库,而应该是消费者的选择

所以最后我真的把多线程和异步代码混淆了,我无法理解异步代码的优点,因为我当时只看了一个方法,而异步代码的真正好处只有在整个项目(或者至少是其中一致的部分)都是按照异步模式编写的情况下才能看到。
例如,在asp.net中,如果没有任何阻塞代码(所有代码都以异步方式编写),那么线程可以在您的客户端等待异步操作时为另一个客户端提供服务,从而提高可伸缩性,在xaml应用程序中,启动异步操作的线程可以立即返回到支持用户界面,而不只是等待操作结束,从而提高响应能力。

根本不要这样做。不要创建
*Async()
方法,除非它们实际上是异步的;切勿在库中调用
Task.Run()
。它在哪里说
Parallel.Invoke
已被弃用?在哪里说明
Task.Run
使用
Parallel.Invoke
?我认为这是使用
线程池的结果
Task.Run
只能用于从UI线程调用CPU绑定的方法。您不想在库中放置包装器的原因是因为您希望能够在任何地方使用(1)。我有一个更详细的计划。而且,(5)是不正确的
Parallel.Invoke
提供了比
Task.Run
和det更多的选项