2010-04-08 4 views
39

Estoy buscando formas de implementar co-rutinas (hilos programados por el usuario) en C#. Cuando usé C++, estaba usando fibras. Veo en Internet que las fibras no existen en C#. Me gustaría obtener una funcionalidad similar.Corutinas en C#

¿Hay alguna forma "correcta" de implementar corutinas en C#?

He pensado en implementar esto utilizando subprocesos que adquieren una sola ejecución mutex + 1 en el hilo del planificador que libera este mutex para cada corrutina. Pero esto parece muy costoso (fuerza un cambio de contexto entre cada corrutina)

También he visto la funcionalidad del iterador de rendimiento, pero según tengo entendido, no puede ceder dentro de una función interna (solo en la función ienumerator original). Entonces esto me hace poco bien.

+0

Enlace: http://blogs.msdn.com/larryosterman/archive/2005/01/05/347314.aspx –

+0

Usted puede encontrar esto es útil/interesante: https://github.com/bvanderveen/coroutine – gsscoder

Respuesta

12

Editar: puede ahora utilizar estos: Is there a fiber api in .net?

Creo que usted debe buscar en el la Reactive Extensions for .NET. Por ejemplo, la declaración coroutines can be simulated using iterators and the yield.

Sin embargo, es posible que desee leer este SO question también.

+0

Los bloques de iterador ya no son relevantes a partir de Rx 2.0, que ahora proporciona sobrecargas de 'Observable.Create' que aceptan una función' Tarea' de retorno, por lo que se combinan la creación de un observable (call/cc) con las corutinas nativas de C# 5 (_async/await_). Esto se puede definir como un "iterador asíncrono". Ver [este hilo] (http://social.msdn.microsoft.com/ Foros/es-ES/6e0ead42-4d89-429d-b6a8-d422cf673390/how-is-the-experimental-createiterator-redundant-with-net-45? Forum = rx) para obtener más información y [la publicación de mi blog] (http: //davesexton.com /blog/post/async-iterators.aspx) para una comparación. –

+0

@DaveSexton - siéntete libre de editar la respuesta –

+0

Hmm, ok gracias. Soy bastante nuevo en SO y no estaba seguro acerca de la etiqueta wiki. Voy a leer las "reglas" primero. –

6

Here es un ejemplo de la utilización de hilos de implementar co-rutinas:

Así hago trampa. Yo uso hilos, pero solo dejo que uno de ellos se ejecute a la vez. Cuando crear una co-rutina, se crea un hilo, y luego hacer un poco de toma de contacto que termina con una llamada a Monitor.Wait(), que bloquea el hilo corrutina - no se ejecutará más hasta que sea desbloqueado. Cuando es hora de llamar a coroutine, hago un traspaso que finaliza con el llamada de subproceso bloqueado, y el subproceso de corrutina ejecutable. Mismo tipo de handoff en el camino de regreso.

Esas entregas son un poco caras, en comparación con otras implementaciones. Si necesita velocidad, querrá escribir su propia máquina de estados y evitar todo este cambio de contexto. (O querrá utilizar un tiempo de ejecución sensible a la fibra - el cambio de las fibras es bastante barato.) Pero si quiere el código expresivo , creo que las coroutines tienen alguna promesa de .

+3

Una limitación con el uso de subprocesos es que (tanto en Winforms como en WPF, creo) los controles de un formulario que fue creado por subproceso 'Larry' no se puede acceder por subproceso' Moe', incluso si el subproceso 'Larry' no está haciendo nada con la forma y será bloqueado hasta que 'Moe' no esté haciendo nada con eso tampoco. Si dos corrutinas pudieran ejecutarse en el mismo subproceso del sistema operativo, podrían compartir recursos que, de otro modo, solo serían utilizables por el hilo de creación. – supercat

10

Creo que con el nuevo .NET 4.5 \ C# 5 el patrón async \ await debería satisfacer sus necesidades.

async Task<string> DownloadDocument(Uri uri) 
{ 
    var webClient = new WebClient(); 
    var doc = await webClient.DownloadStringTaskAsync(url); 
    // do some more async work 
    return doc; 
} 

Sugiero mirar http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DEV411 para obtener más información. Es una gran presentación.

También http://msdn.microsoft.com/en-us/vstudio/gg316360 tiene mucha información.

Si está utilizando una versión anterior de .NET, hay un CTP Async disponible para .NET más antiguo con una licencia de activación para que pueda usarlo en entornos de producción.Aquí hay un enlace al CTP http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

Si no le gusta ninguna de las opciones anteriores, creo que podría seguir el patrón de iterador asíncrono como se describe aquí. http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

0

Te puede interesar this es una biblioteca que oculta el uso de corutinas. Por ejemplo, para leer un archivo:

//Prepare the file stream 
FileStream sourceStream = File.Open("myFile.bin", FileMode.OpenOrCreate); 
sourceStream.Seek(0, SeekOrigin.End); 

//Invoke the task 
yield return InvokeTaskAndWait(sourceStream.WriteAsync(result, 0, result.Length)); 

//Close the stream 
sourceStream.Close(); 

Esta biblioteca utiliza un hilo para ejecutar todas corrutinas y permitir llamar a la tarea para las operaciones verdaderamente asíncronos. Por ejemplo, para llamar a otro método como una co-rutina (también conocido como rendimiento para su retorno

//Given the signature 
//IEnumerable<string> ReadText(string path); 

var result = new Container(); 
yield return InvokeLocalAndWait(() => _globalPathProvider.ReadText(path), container); 
var data = container.RawData as string;