Suggerimenti per fare async I / O con il Task Parallel Biblioteca
-
26-09-2019 - |
Domanda
Ho qualche codice di trasferimento di file ad alta prestazione che ho scritto in C # utilizzando il modello di programmazione asincrona (APM) linguaggio (ad esempio, BeginRead
/ EndRead
). Questo codice legge un file da un disco locale e lo scrive in una presa.
Per ottenere le migliori prestazioni su hardware moderno, è importante mantenere più di una straordinaria operazione di I / O in volo, quando possibile. Così, ho posto diverse operazioni BeginRead
sul file, poi, quando si completa, che io chiamo un BeginSend
sul socket, e quando che completa faccio un'altra BeginRead
sul file. I dettagli sono un po 'più complicato di così, ma per l'alto livello che è l'idea.
Ho il codice di lavoro APM-based, ma è molto difficile da seguire e probabilmente ha bug di concorrenza sottili. Mi piacerebbe utilizzare TPL per questo, invece. I Task.Factory.FromAsync
figurato sarebbe solo di farlo, ma c'è un problema.
Tutti i campioni di I / O che ho visto (in modo particolare la classe StreamExtensions
nel parallelo estensioni Extra) assumere una LEGGI seguito da una scrittura. Questo non eseguirà la necessità mio modo.
Non è possibile utilizzare qualcosa di semplice come Parallel.ForEach
o l'estensione Task.Factory.Iterate
Extra perché i compiti asincrone di I / O non spendere molto tempo su un thread di lavoro, in modo parallelo appena si avvia un altro compito, con conseguente potenzialmente decine o centinaia di in attesa di operazioni di I / O; modo troppo! È possibile risolvere che Wait
ing sui vostri compiti, ma che provoca la creazione di un manico evento (un oggetto di kernel), e un'attesa di blocco su un manico compito attesa, che lega in su un thread di lavoro. La mia implementazione APM-based evita entrambe le cose.
Ho suonato in giro con diversi modi per mantenere più operazioni di lettura / scrittura in volo, e sono riuscito a farlo utilizzando continuazioni che chiamare un metodo che crea un altro compito, ma ci si sente a disagio, e sicuramente doesn' t voglia TPL idiomatica.
Qualcun altro ha cimentati con un problema come questo con il TPL? Qualche suggerimento?
Soluzione
Se siete preoccupati per troppi thread, si può semplicemente insieme ParallelOptions.MaxDegreeOfParallelism
ad un numero accettabile nella vostra chiamata a Parallel.ForEach
.