2010-04-08 14 views
39

Sto cercando modi per implementare le co-routine (thread pianificati dall'utente) in C#. Usando il C++ stavo usando le fibre. Vedo su internet le fibre non esistono in C#. Mi piacerebbe avere una funzionalità simile.Coroutine in C#

Esiste un modo "giusto" per implementare le coroutine in C#?

Ho pensato di implementare questo utilizzando thread che acquisiscono un singolo mutex di esecuzione + 1 sul thread dello scheduler che rilascia questo mutex per ogni coroutine. Ma questo sembra molto costoso (forza un cambio di contesto tra ogni coroutine)

Ho anche visto la funzionalità di iteratore di rendimento, ma come ho capito non puoi cedere all'interno di una funzione interna (solo nella funzione di ienumerator originale). Quindi questo mi fa poco bene.

+0

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

+0

Si possono trovare questo utile/interessante: https://github.com/bvanderveen/coroutine – gsscoder

risposta

12

Edit: È ora possibile utilizzare questi: Is there a fiber api in .net?

Credo che si dovrebbe guardare la la Reactive Extensions for .NET. Ad esempio, dichiarazione coroutines can be simulated using iterators and the yield.

Tuttavia si consiglia di leggere anche questo SO question.

+0

I blocchi Iterator non sono più rilevanti a partire da Rx 2.0, che ora fornisce overload di 'Observable.Create' che accetta una funzione' Task'-return, quindi conflating la creazione di un osservabile (call/cc) con le coroutine native di C# 5 (_async/await_). Questo può essere definito come un "iteratore asincrono". Vedere [questo thread] (http://social.msdn.microsoft.com/ Forum/it-it/6e0ead42-4d89-429d-b6a8-d422cf673390/how-is-the-experimental-creaiterator-ridondante-con-net-45? Forum = rx) per maggiori informazioni e [il mio post sul blog] (http: //davesexton.com /blog/post/async-iterators.aspx) per un confronto. –

+0

@DaveSexton - sentiti libero di modificare la risposta –

+0

Hmm, ok grazie. Sono abbastanza nuovo per SO e non ero sicuro dell'etichetta del wiki. Prima leggerò le "regole". –

6

Here è un esempio di utilizzo di thread per implementare coroutine:

Così ho barare. Io uso thread, ma io solo lasciare che uno di loro venga eseguito alla volta. Quando io creo un coroutine, creo un filo, e poi fare un po 'strette di mano che termina con una chiamata a Monitor.Wait(), che blocca il filo coroutine - non funzionerà più fino a quando è sbloccato. Quando è il momento di chiamare la coroutine, eseguo un trasferimento che termina con il thread di chiamata bloccato e il thread di coroutine eseguibile. Stesso tipo di trasferimento al ritorno.

Questi handoff sono costosi, rispetto ad altre implementazioni. Se hai bisogno di velocità, ti consigliamo di scrivere il tuo computer di stato , e evitare tutto questo cambio di contesto. (Oppure si vorrà utilizzare un runtime in fibra ottica - le fibre di commutazione sono piuttosto economiche .) Ma se si desidera il codice espressivo , penso che le coroutine contengano qualche promessa .

+3

Una limitazione con l'utilizzo dei thread è che (sia in Winforms che in WPF, credo) i controlli di un modulo creato dal thread 'Larry' non sono accessibili dal thread' Moe', anche se il thread 'Larry' non sta facendo nulla con il modulo e sarà bloccato fino a quando 'Moe' non sta facendo nulla con esso neanche. Se due coroutine potrebbero essere eseguite sullo stesso thread del sistema operativo, potrebbero condividere risorse che sono altrimenti utilizzabili solo dal thread di creazione. – supercat

10

Credo che con il nuovo .NET 4.5 \ C# 5 il modello asincrono/atteso dovrebbe soddisfare le vostre esigenze.

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

Suggerisco di guardare http://channel9.msdn.com/Events/TechEd/Australia/Tech-Ed-Australia-2011/DEV411 per ulteriori informazioni. È una grande presentazione.

Anche http://msdn.microsoft.com/en-us/vstudio/gg316360 ha alcune grandi informazioni.

Se si utilizza una versione precedente di .NET, è disponibile un CTP Async per .NET precedente con licenza go live in modo da poterlo utilizzare negli ambienti di produzione.Ecco un collegamento al CTP http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

Se non ti piace nessuna delle opzioni di cui sopra, credo che potresti seguire lo schema iteratore asincrono come descritto qui. http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=9983

0

this è una libreria che nasconde l'utilizzo di coroutine. Ad esempio, per leggere un file:

//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(); 

Questa libreria utilizza un thread per eseguire tutti coroutine e permettere di richiamare il compito per le operazioni asincrone veramente. Ad esempio, per chiamare un altro metodo come un coroutine (aka cedendo per il suo ritorno

//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; 
Problemi correlati