2011-08-18 49 views
11

最近,我偶然发现了AsyncEnumerator类窗体Jeffrey Richter的Power Threading Library,它似乎解决了编程异步时通常会遇到的几个问题。我们还需要Richter的AsyncEnumerator吗?

这个类的想法已经存在了很长一段时间了,我想知道如果.NET/C#的当前版本现在已经内置了对这种机制的支持,或者它仍然需要依赖第三方库?或者,也许更新版本的.NET有一些其他方法可以像Richter的AsyncEnumerator一样简化异步编程?

换句话说:有没有理由今天不开始使用Richter的AsyncEnumerator?

编辑:

与信息上AsyncEnumerator某些链接:

回答

16

是的,你仍然可以从我的AsyncEnumerator中受益。在.NET 4(任务,并行,PLINQ等)中引入的新线程化内容都是关于并发性的。也就是说,它们都是关于将计算工作量分解并将其划分到多个线程中,以便工作负载可以在比使用1个线程执行整个工作负载所需的时间更少的时间内完成。您可以使用这些结构同时执行多个同步I/O操作。但是,同步I/O操作会导致所有线程阻塞,从而导致线程池创建更多线程。所以,当您的应用程序的资源使用率高涨时,您的CPU使用率仍然很低。这对于实现您的应用程序非常低效,并且会阻止您的应用程序扩展。

我的AsyncEnumerator是关于启动异步I/O操作而不阻塞任何线程,以便您的应用程序的资源使用率保持非常低,因此您的应用程序可以很好地扩展。在这种情况下,CPU使用率仍然很低,因为您正在执行I/O;不是一个计算工作量。

在.NET的下一个版本中,新的async/await语言功能(我与Microsoft合作)使您能够执行异步I/O,实际上,新功能的建模与我的AsyncEnumerator 。以便您可以将使用AsyncEnumerator的代码移植到新模型中,而只需更改很少的源代码。

正如其他人指出的,我的AsyncEnumerator还提供了其他功能,并且可以与.NET 2.0及更高版本一起使用。所以,很多人仍然会发现很长一段时间它非常有用。

+0

感谢您的解释!我开始使用你的图书馆,我对它很满意。但是我不确定如何正确实现异常处理。也许你可以看看我的另一个问题[这里](http:// stackoverflow。COM /问题/ 7122164 /异常处理 - 当 - 实现最APM图案与-asyncenumerator)。非常感谢! –

9

一个明显的平行这里是PLINQ,但里希特本人dismisses this

杰弗里里希特2008年12月4日在2:27 PMquotereply他们非常 不同。 Parallel.For特别是关于在机器中的所有CPU 上并行扩展执行一堆计算绑定操作。我的AsyncEnumerator主要是发布一个或多个并发的I/O绑定操作,而不需要任何线程块来完成 。

然而,C#async CTP可以在这里很有用,使得螺纹延续更为合理,即

var bytesRead = await stream.ReadAsync(...); 
Console.WriteLine(bytesRead); // woah! we're on a different thread now! 

这里,C#编译器重新写入各地await instuctions,这样就变成了一切回调/继续到现有的异步操作(它必须返回一个“awaitable”值)。一旦这个产品投入使用,我希望这将成为一种更自然的编写具有异步延迟的代码。

+0

从我见过的PLINQ我也不认为它是一个明显的并行。我喜欢AsyncEnumerator的是,您可以用一种非常自然的方式表达一系列异步操作(如连接到Web服务器,根据请求的某些数据请求一些数据)。这一切看起来像一个同步程序。最重要的是,你有支持取消/超时,你不必担心编组到UI线程。我不明白我能用PLINQ处理这样的事情。 –

+0

@Robert,它正是***正在等待的东西,它也是 - 在看起来很规则的C#中。 'var response = await GetResponse();'etc –

+0

关于await关键字...我想坚持使用目前可用的(我正在写产品代码) –

0

从这个问题Asynchronous iterator Task<IEnumerable<T>>

这听起来像你可能真的要的是像IObservable<T>,这是有点像基于推送的异步的IEnumerable <牛逼>。请参阅Microsoft Open Technologies(代码为Apache-2.0许可的代码)的Reactive Extensions, a.k.a. Rx,这些大量主要方法与IObservable <T>一起使用,以使其像LINQ到对象等一样工作。

IEnumerable <T>的问题在于没有任何东西真正使枚举本身异步。如果你不希望添加的Rx上的依赖(这实在是什么使的IObservable <牛逼>闪耀),这种替代可能会为你工作:

public async Task<IEnumerable<char>> TestAsync(string testString) 
{ 
    return GetChars(testString); 
} 

private static IEnumerable<char> GetChars(string testString) 
{ 
    foreach (char c in testString.ToCharArray()) 
    { 
     // do other work 
     yield return c; 
    } 
} 

但我想指出在不知道实际上正在异步完成的情况下,可能有更好的方法来实现您的目标。您发布的任何代码都不会异步执行任何操作,而且我也不知道// do other work中的任何内容是否是异步的(在这种情况下,这不是您的底层问题的解决方案,尽管它会让您的代码编译)。

相关问题