你如何使用C#进行协同例程?

WeN*_*ers 10 c# python coroutine system.reactive

在python中,yield关键字可以在push和pull上下文中使用,我知道如何在c#中执行pull上下文,但是如何实现push.我发布了我试图在c#中从python中复制的代码:

def coroutine(func):
  def start(*args,**kwargs):
    cr = func(*args,**kwargs)
    cr.next()
    return cr
  return start

@coroutine
def grep(pattern):
  print "Looking for %s" % pattern
  try:
    while True:
      line = (yield)
      if pattern in line:
        print line,
  except GeneratorExit:
    print "Going away. Goodbye"
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 14

如果您想要的是一个"可观察的集合" - 即一个向您推送结果而不是让消费者拉动它们的集合 - 那么您可能希望查看Reactive Framework扩展.这是一篇关于它的文章:

http://www.infoq.com/news/2009/07/Reactive-Framework-LINQ-Events

现在,正如您所注意到的,如果您有可用的协程,则可以轻松构建"push"和"pull"样式迭代器.(或者,正如Thomas指出的那样,你也可以使用continuation来构建它们.)在当前版本的C#中,我们没有真正的协程(或者continuation).但是,我们非常关注用户对异步编程的痛苦.

将基于光纤的协程实现为一流的语言特性是一种可能用于使异步编程更容易的技术,但这只是我们目前研究的许多可能的想法.如果你有一个非常可靠的场景,其中协同程序比其他任何东西都做得更好 - 包括反应框架 - 那么我很想听到更多关于它的信息.关于异步编程中人们面临的实际问题,我们获得的数据越真实,我们就越有可能提出一个好的解决方案.谢谢!

更新:我们最近宣布,我们正在为下一版本的C#和VB添加类似协程的异步控制流程.您可以使用我们的社区技术预览版本自行尝试,您可以在此下载.


Tho*_*nin 7

C#没有通用的协同例程.一般的协同例程是协同例程具有自己的堆栈,即它可以调用其他方法,并且这些方法可以"产生"值.一般协同例程的实现需要使用堆栈进行一些智能操作,可能包括在堆上分配堆栈帧(包含局部变量的隐藏结构).这可以做到,有些语言就是这样做的(例如Scheme),但要做到这一点有点棘手.此外,许多程序员发现该功能难以理解.

可以使用线程模拟常规协同例程.每个线程都有自己的堆栈.在协同例程设置中,两个线程(初始调用者和协同例程的线程)将交替控制,它们实际上永远不会同时运行.然后,"yield"机制是两个线程之间的交换,因此它很昂贵(同步,通过OS内核和调度程序的往返......).此外,内存泄漏的空间很大(协同例程必须明确"停止",否则等待线程将永远存在).因此,很少这样做.

C#提供了一个称为迭代器的混合协同特性.C#编译器自动将迭代器代码转换为特定的状态类,局部变量成为类字段.然后,在VM级别,Yielding是平原return.只要从迭代器代码本身执行"yield",而不是从迭代器代码调用的方法执行,就可以做到这样的事情.C#迭代器已经涵盖许多用例和C#的设计师们不愿进一步往下走的道路延续.一些讽刺的人热衷于声明实现全功能的延续将阻止C#像其主要的敌人Java一样高效(有效的延续是可行的,但这需要与GC和JIT编译器进行相当多的工作).