最近我偶然发现了AsreyEnumerator类表格Jeffrey Richter的Power Threading Library,它似乎解决了我在编写异步内容时经常遇到的几个问题。
这个类的想法已经存在了很长一段时间了,我想知道当前版本的.NET / C#是否已经内置了对这种机制的支持,或者是否还需要依赖第三种党的图书馆?或者也许新版本的.NET有一些替代方法可以像Richter的AsyncEnumerator那样简化异步编程?
或换句话说:今天有没有理由不开始使用Richter的AsyncEnumerator?
编辑:
有关AsyncEnumerator的信息的一些链接:
答案 0 :(得分:16)
是的,您仍然可以从我的AsyncEnumerator中受益。 .NET 4(Tasks,Parallel,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及更高版本。因此,许多人在很长一段时间内仍然会发现它非常有用。
答案 1 :(得分:9)
这里显而易见的是PLINQ,但里希特本人dismisses this:
Jeffrey Richter 2008年12月4日下午2:27quotereply他们非常 不同。 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
个版本周围重写所有内容,使其成为现有异步操作(必须返回“等待”值)的回调/继续。一旦生产中,我希望这将成为一种更自然的方式来编写由于异步而导致内在延迟的代码。
答案 2 :(得分:2)
.net 4.0包括PLINQ框架和各种其他线程计算方法。
有关详细信息,请参阅Parallel Programming in the .NET Framework。
答案 3 :(得分:0)
从这个问题Asynchronous iterator Task<IEnumerable<T>>:
听起来你可能真正想要的是类似IObservable<T>的东西,它有点像基于推送的异步IEnumerable&lt; T&gt;。有关使用IObservable&lt; T&gt;的大量方法,请参阅Microsoft Open Technologies的Reactive Extensions, a.k.a. Rx(Apache-2.0下许可的代码)(无联属关系)。使它像LINQ-to-Objects等工作。
IEnumerable&lt; T&gt;的问题没有什么能真正使枚举本身异步。如果您不想在Rx上添加依赖项(这实际上是使IObservable&lt; T&gt;闪耀的原因),这个替代方案可能适合您:
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
中的任何内容是否异步(在这种情况下,这不是解决您的根本问题的方法,尽管它会让你的代码编译)。