我们还需要Richter's AsyncEnumerator吗?

本文关键字:AsyncEnumerator Richter 我们 | 更新日期: 2023-09-27 18:05:53

最近我偶然发现了jeffery Richter的Power Threading Library中的AsyncEnumerator类,它似乎解决了我在编程异步内容时经常遇到的几个问题。

这个类的想法已经存在了很长一段时间了,我想知道当前版本的。net/c#是否已经内置了对这种机制的支持,或者是否仍然需要依赖第三方库?或者,也许新版本的。net有一些替代方法,可以像Richter的AsyncEnumerator那样简化异步编程?

或者换句话说:今天有理由不开始使用Richter的AsyncEnumerator吗?编辑:

关于AsyncEnumerator的一些链接:

  • Jeffrey Richter和他的AsyncEnumerator
  • 使用AsyncEnumerator简化APM
  • 更多AsyncEnumerator功能

我们还需要Richter's AsyncEnumerator吗?

是的,您仍然将受益于我的AsyncEnumerator。. net 4中引入的新线程功能(任务、并行、PLINQ等)都是关于并发的。也就是说,它们都是关于计算工作负载,将其划分并生成到多个线程中,以便工作负载可以在比1个线程处理整个工作负载更短的时间内完成。您可以使用这些构造并发地执行多个同步I/O操作。但是,同步I/O操作会导致所有线程阻塞,从而导致线程池创建更多线程。因此,你的应用程序的资源使用飙升,而你的CPU使用仍然非常低。这是一个非常低效的实现你的应用程序,并防止你的应用程序的扩展。

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

在。net的下一个版本中,新的async/await语言特性(我与微软合作开发的)使您能够执行异步I/O,实际上,新特性的建模与我的AsyncEnumerator非常相似。这样你就可以将使用我的AsyncEnumerator的代码移植到新模型中,只需要很少的源代码更改。

正如其他人指出的那样,我的AsyncEnumerator仍然提供其他功能,并且可以与。net 2.0及更高版本一起工作。因此,许多人在很长一段时间内仍然会发现它很有用。

一个明显的相似之处是PLINQ,但Richter自己对此不屑一顾:

Jeffrey Richter Dec 04, 2008 at 2:27 pm不同。平行的。特别是关于执行一堆在所有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指令周围的所有内容,这样它就变成了对现有异步操作的回调/延续(必须返回一个"可等待"的值)。一旦进入生产环境,我希望这将成为一种更自然的方式来编写由于异步而导致的内在延迟的代码。

.net 4.0包括PLINQ框架和其他各种线程计算方法。

参见。net框架中的并行编程。

从这个问题异步迭代器Task>:

听起来你可能真正要找的是IObservable,它有点像一个基于push的异步IEnumerable。参见Microsoft Open Technologies的Reactive Extensions,也就是Rx(在Apache-2.0许可下的代码)(没有从属关系),其中有大量与IObservable让它像LINQ-to-Objects那样工作。

IEnumerable没有什么能让枚举本身异步化。如果你不想添加对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中是否有任何东西是异步的(在这种情况下,这不是解决你的潜在问题,尽管它会使你的代码编译)。