2013-12-09 40 views
4

我有很多Utils类,我用于许多不同的项目,其中大多数是静态的,通常甚至不会互相调用。我的意图是利用新的异步/等待功能,但不重写所有的东西,所以我的问题是:我可以添加一个新的方法为每个现有的方法命名MethodAsync与Task.Run((()=>方法名)?用异步/等待重写我的Utils库的正确方法

例如:

//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绑定方法。

如果我正确理解,每个异步方法都按定义包含一个等待对象,它是一个Task或另一个异步方法。

这意味着,只要我可以使用异步.NET方法,我应该等待它,并将我的调用方法标记为异步。

但是,其他任何不调用任何异步方法但需要一些时间才能完成的方法应该使用Task.Run调用进行调用。

对不对?

编辑

,所以我已阅读全部张贴链接,MSDN上的最佳实践和一些博客文章,但我仍然需要一个完整的程序来遵循新的异步编码时/等待功能。 这是我到目前为止:

1)具有异步替代的每个.NET方法应该使用异步替代。 (据我所知,.NET异步方法已经存在,只适用于可以异步的方法)。 2)每个使用异步方法的方法也应该做成异步。 3)每个不使用异步方法的方法(因为没有可用的)但仍需要一些cpu时间来执行应该通过使用Task.Run包装它们来实现异步(我知道在这种情况下它应该是使用Task.Run的客户端,如果他们想要的话,但因为我只为那些需要超过50ms执行的方法添加这些包装器,并且仍然可以使用该方法的非异步版本,所以我仍然不明白为什么我不应该把这个包装放入库中)。

4)每一个需要非cpu-time的方法都会导致它等待其他资源(如internet,数据库,事件等等)应该使用TaskFactory.FromAsync或TaskCompletionSource。

5)现在不推荐使用System.Threading.Tasks.Parallel.Invoke(method1,method2等)。从我读的Task.Run已经运行并发线程,如果CLR认为需要并发。所以看起来Task.Run已经在需要的时候使用了Parallel.Invoke。

+11

不要那样做。除非它们实际上是异步的,否则不要创建'* Async()'方法;永远不要在库中调用Task.Run()。 http://msdn.microsoft.com/en-us/magazine/jj991977.aspx – SLaks

+1

[我应该公开同步方法的异步包装?](http://blogs.msdn.com/b/pfxteam/archive/2012/ 04/13/10293638.aspx) – ken2k

+0

它说'Parallel.Invoke'已被弃用?它在哪里声明'Task.Run'使用'Parallel.Invoke'?我认为它导致了'ThreadPool'的使用。 – Lukazoid

回答

6

我终于能找到清除我所有的疑虑良好的资源:

第一个是“基于任务的异步模式”可在http://www.microsoft.com/en-us/download/details.aspx?id=19957 本文档介绍了异步/ AWAIT功能,如何/时使用它,它包含了很多实际的例子和一些非常有用的静态方法,我现在正在每个项目中使用!

第二个是“异步的禅:为最佳性能的最佳做法”,可http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-829T 这是异步功能的完整概述,与并行功能的一些报道,同时也解释了为什么它永远也不应该使用Task.Run()方法的库,但它应该是消费者选择。

所以最后我真的很困惑多线程与异步代码,我无法领会异步代码的优点,因为我只是在看当时的单一方法,而异步代码的真正好处只能看到如果整个项目(或至少它的一致部分)是按照异步模式编写的。 例如在asp.net中,如果没有任何阻塞代码(一切都以异步方式编写),那么当你的一个线程正在等待一个异步操作时,一个线程可以服务另一个客户端,从而提高可伸缩性,而在一个xaml应用程序中启动异步操作的线程可以立即返回到支持您的UI,而不是等待该操作结束,从而提高响应速度。

+0

+1为了做一些真正的发现,我喜欢谈论“异步的禅宗”。当你在等待一些外部资源时,async/await的真正优点就来了,例如文件系统,数据库,一些网络流量,系统互斥等。另请参阅[本答案](http://stackoverflow.com/a/18015586/921321)以获取何时使用'Task.Run' – Lukazoid

5

这在Should I expose asynchronous wrappers for synchronous methods?讨论这篇文章,我想强调的部分,为什么这是不好的设计为低于:

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

很显然,我建议你阅读整篇文章太多,但我希望上面的亮点有很大原因暴露*Async()方法在一个库中不应该换行同步的。

我希望这会有所帮助。