Sto utilizzando un BlockingCollection
per implementare un modello produttore/consumatore. Ho un ciclo asincrono che riempie la collezione con i dati da elaborare che possono poi essere raggiunti dal client in un momento successivo. I pacchetti arrivano scarsamente e vorrei che il polling fosse fatto senza usare una chiamata bloccante.Asincrono Presa dal blocco della raccolta
In sostanza, sto cercando qualcosa come un BeginTake
e EndTake
che non esiste nella raccolta di blocco in modo che io possa fare uso del pool di thread interno in un callback. Non deve essere un BlockingCollection
con qualsiasi mezzo. Tutto ciò che fa ciò di cui ho bisogno sarebbe fantastico.
Questo è quello che ho ora. _bufferedPackets
è un BlockingCollection<byte[]>
:
public byte[] Read(int timeout)
{
byte[] result;
if (_bufferedPackets.IsCompleted)
{
throw new Exception("Out of packets");
}
_bufferedPackets.TryTake(out result, timeout);
return result;
}
mi piacerebbe che questo sia qualcosa di simile, in pseudocodice:
public void Read(int timeout)
{
_bufferedPackets.BeginTake(result =>
{
var bytes = _bufferedPackets.EndTake(result);
// Process the bytes, or the resuting timeout
}, timeout, _bufferedPackets);
}
Quali sono le opzioni per questo? Non voglio posizionare lo qualsiasi thread in uno stato di attesa, dal momento che ci sono molti altri elementi di I/O da elaborare, e mi troverei a corto di thread abbastanza rapidamente.
Aggiornamento: Ho riscritto il codice in questione per utilizzare il processo asincrono in modo diverso, essenzialmente scambiando i callback in base a se c'è una richiesta in attesa entro il limite di timeout. Funziona bene, ma sarebbe comunque fantastico se ci fosse un modo per farlo senza ricorrere ai timer e scambiando lambda attorno a chi potenzialmente causa condizioni di gara ed è difficile da scrivere (e capire). Ho risolto questo anche con una propria implementazione di una coda asincrona, ma sarebbe comunque fantastico se esistesse un'opzione più standard e ben testata.
Al momento, penso che nessuna raccolta di TPL fornisca metodi asincroni ad eccezione di ObservableCollection per l'interfaccia utente. Cosa ne pensi ? –
È possibile eseguire il wrapping in un 'Task task = Task.Factory.StartNew (() => {// Il codice restituisce byte []});' tuttavia questo non è elligente e deve esserci un modo migliore .. –
MoonKnight
Il wrapping in un'attività comporterà un'attività che verrà bloccata in un handle di attesa. Dal momento che ci sono molti compiti in corso che occuperanno un compito per sempre che mi farà esaurire i compiti nella piscina, purtroppo. – Dervall