2010-03-22 7 views
9

En python, la palabra clave yield se puede usar en contextos push y pull, sé cómo hacer el contexto pull en C#, pero cómo lograré el push. Publiqué el código que intento replicar en C# de python:¿Cómo se pueden hacer Co-rutinas usando C#?

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" 
+0

Eric Lippert tiene una publicación de blog en este lugar –

+1

Considere formatear su código un poco más usando pestañas/espacios. – Mizipzor

+3

formateo de pestañas ... de hecho es necesario y no importa el tiempo, es asunto de Python. –

Respuesta

13

Si lo que desea es una "colección observable", es decir, una colección que empuja los resultados hacia usted en lugar de dejar que el consumidor los tire, entonces probablemente quiera examinar las extensiones de Reactive Framework. He aquí un artículo sobre ella:

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

Ahora, a medida que tenga en cuenta, se puede construir tanto "push" y "pull" iteradores estilo fácilmente si tiene corrutinas disponibles. (O, como Thomas señala, también puede compilarlos con continuaciones). En la versión actual de C#, no tenemos corutinas verdaderas (o continuaciones). Sin embargo, estamos muy preocupados por el dolor que sienten los usuarios alrededor de programación asincrónica.

La implementación de corutinas basadas en fibra como una característica de lenguaje de primera clase es una técnica que podría usarse para facilitar la programación asíncrona, pero esa es solo una idea posible de muchas de las que estamos investigando actualmente.Si tienes un escenario increíblemente sólido donde corutines hacen un mejor trabajo que cualquier otra cosa, incluido el marco reactivo, entonces me encantaría saber más sobre él. Los datos más realistas que tenemos sobre los problemas reales que enfrentan las personas en la programación asincrónica, es más probable que encontremos una buena solución. ¡Gracias!

ACTUALIZACIÓN: Recientemente hemos anunciado que estamos agregando flujos de control asíncrono similar a Coroutine a la próxima versión de C# y VB. Puede probarlo usted mismo con nuestra edición Community Technology Preview, que puede descargar here.

+0

Uno de estos casos es Simulación dirigida por eventos (estilo Simula). Tengo un proyecto que usa fibras Win32 que todavía no puedo transferir a .NET –

+0

Creo que la programación asincrónica en C# es excelente. Sin embargo, me gusta el MailboxProcessor de Erlang en F #. En cuanto a las co-rutinas, las encuentro muy interesantes. Sé que son tecnología antigua y que se eliminaron cuando se introdujeron los hilos, pero me gusta la idea de que sé exactamente cuándo se ejecutará una rutina y cuándo se le devolverá el control. El problema principal que encuentro con los hilos es la falta de control y la pesadez general de crearlos. Sin embargo, proporcionan un buen nivel de abstracción de pensamiento, que requieren muy poco esfuerzo para implementar :) – WeNeedAnswers

+0

Gracias Eric. ¡Suena muy prometedor! – WeNeedAnswers

6

C# no tiene generales co-rutinas. Una co-rutina general es cuando la co-rutina tiene su propia pila, es decir, puede invocar otros métodos y esos métodos pueden "ceder" valores. La implementación de co-rutinas generales requiere hacer algunas cosas inteligentes con pilas, posiblemente hasta e incluyendo la asignación de montones de pila (las estructuras ocultas que contienen variables locales) en el montón. Esto se puede hacer, algunos idiomas hacen eso (por ejemplo, Scheme), pero es un poco complicado hacerlo bien. Además, muchos programadores encuentran la característica difícil de entender.

Las co-rutinas generales se pueden emular con subprocesos. Cada hilo tiene su propia pila. En una configuración de co-rutina, ambos hilos (el llamador inicial y el hilo para la co-rutina) alternarán el control, nunca se ejecutarán de manera simultánea. El mecanismo de "rendimiento" es entonces un intercambio entre los dos hilos, y como tal es costoso (sincronización, una ida y vuelta a través del kernel y programador del sistema operativo ...). Además, hay mucho espacio para las pérdidas de memoria (la co-rutina debe ser explícitamente "detenida", de lo contrario, el hilo de espera se mantendrá para siempre). Por lo tanto, esto rara vez se hace.

C# proporciona una característica de co-rutina bastardized-down llamada iterators. El compilador de C# convierte automáticamente el código del iterador en una clase de estado específica, con las variables locales convirtiéndose en campos de clase. El rendimiento es entonces, en el nivel VM, un simple return. Tal cosa es factible siempre que el "rendimiento" se realice desde el código del iterador en sí mismo, no desde un método invocado por el código del iterador. Los iteradores de C# ya cubren muchos casos de uso y los diseñadores de C# no estaban dispuestos a ir más allá en el camino al continuations. Algunas personas sarcásticas están dispuestas a afirmar que la implementación de continuas con todas las funciones habría evitado que C# fuera tan eficiente como su archienemigo Java (las continuaciones eficientes son factibles, pero esto requiere bastante trabajo con el GC y el compilador JIT).

+0

nice answer. Creo que encontré lo que estaba tratando de hacer con C#, IObservable. Eso de la pila, hace Python bajo las sábanas hacer eso, porque no creo que lo haga. Utiliza vainilla C.Sin embargo, no lo sé con certeza. Estoy tratando de evitar todo el uso de subprocesos, de ahí que me interese la raíz de la co-rutina. Me parece que si tengo el control total de mi programación y tengo las herramientas para evitar los hilos, ¿por qué no intentarlo? El material de coroutine debería funcionar como un regalo, ya sea que esté envuelto en la falsedad IObservable :) – WeNeedAnswers

+0

Java eficiente ... :) lo siento que me hizo sonreír. Recuerdo haber hecho una solución usando JBoss. la cosa no liberaría objetos, le dijimos a nuestro cliente final (T.U.I. --- Thomas Cook) que tendría que volver a encenderla y apagarla de vez en cuando. :) – WeNeedAnswers

+1

Si no te gusta Java, en cuanto a eficiencia, entonces es probable que tampoco estés muy contento con C#. Son bastante similares a ese respecto. En realidad son bastante similares en cada vista. –

0

Me encantaría ver una API basada en fibra para .Net.

Intenté utilizar la API de fibra nativa en C# mediante p/invoke hace un tiempo, pero debido a que el manejo de excepciones del tiempo de ejecución (incorrectamente) hace suposiciones basadas en subprocesos, las cosas se rompieron (mal) cuando ocurrieron excepciones.

Una "aplicación asesina" para una API de corrutina basada en fibra es la programación de juegos; ciertos tipos de IA requieren un hilo "liviano" que puede cortar a tiempo. Por ejemplo, los árboles de comportamiento del juego requieren la capacidad de "pulsar" el código de decisión en cada cuadro, lo que permite que el código de IA ceda cooperativamente a la persona que llama cuando el segmento de decisión está activo. Esto es posible implementarlo con hilos duros, pero mucho, mucho más complicado.

Por lo tanto, si bien los casos de uso de fibra verdadera no son convencionales, definitivamente existen, y un pequeño nicho de nosotros. Los codificadores de .Net alentarían enormemente si se resolvieran los errores existentes en el subsistema de fibra.

1

En realidad, .NET no hace "suposiciones incorrectas" sobre la afinidad de subprocesos, de hecho desacopla por completo la noción de un subproceso de nivel .NET desde el subproceso de nivel de sistema operativo.

Lo que tienes que hacer es asociar un estado de subproceso lógico de .NET con tu fibra (para eso necesitas la API de Hosting de CLR pero no necesitas escribir un host tú mismo puedes usar los necesarios desde tu propia aplicación directamente) y todo, el seguimiento de bloqueo, el manejo de excepciones funciona normalmente de nuevo.

Un ejemplo se puede encontrar aquí: http://msdn.microsoft.com/en-us/magazine/cc164086.aspx

BTW Mono 2.6 contiene soporte Coroutine bajo nivel y se puede utilizar para poner en práctica todas las primitivas de nivel más alto fácilmente.

0

Bueno, probé a desarrollar una biblioteca completa para administrar corutinas con un solo hilo. La parte más difícil fue llamar corutinas dentro de corutinas ... y devolver parámetros, pero finalmente alcancé un muy buen resultado here. La única advertencia es que las operaciones de bloqueo de E/S se deben realizar a través de tareas y todo el "retorno" se debe reemplazar con "retorno de rendimiento". Con el servidor de aplicaciones basado en esta biblioteca, pude casi duplicar las solicitudes realizadas con un estándar async/await basado en IIS. (Busque Node.Cs y Node.Cs.Musicstore en github para probarlo en casa)

Cuestiones relacionadas