Estoy usando un BlockingCollection
para implementar un patrón de productor/consumidor. Tengo un bucle asíncrono que llena la colección con los datos que se procesarán, que luego pueden ser accedidos por el cliente mucho más tarde. Los paquetes llegan escasamente y me gustaría que la votación se realice sin usar una llamada de bloqueo para tomar.Toma asincrónica de la colección de bloqueo
En esencia, estoy buscando algo así como un BeginTake
y EndTake
que no existe en la colección de bloqueo para que pueda hacer uso del grupo de subprocesos interno en una devolución de llamada. No tiene que ser un BlockingCollection
de ninguna manera. Cualquier cosa que haga lo que necesito sería genial.
Esto es lo que tengo ahora. _bufferedPackets
es una 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;
}
me gustaría que esto es algo como esto, en pseudocódigo:
public void Read(int timeout)
{
_bufferedPackets.BeginTake(result =>
{
var bytes = _bufferedPackets.EndTake(result);
// Process the bytes, or the resuting timeout
}, timeout, _bufferedPackets);
}
¿Cuáles son mis opciones para este? No quiero colocar ningún hilo en estado de espera, ya que hay muchas otras cosas IO que procesar, y me quedaría sin hilos bastante rápido.
Actualización: He reescrito el código en cuestión de utilizar el proceso asíncrono de manera diferente, cambiando esencialmente devoluciones de llamada en base a si hay una solicitud de espera dentro del límite de tiempo de espera. Esto funciona bien, pero igual sería increíble si hubiera una forma de hacerlo sin tener que recurrir a temporizadores e intercambiar lambdas, lo que potencialmente causa condiciones de carrera y es difícil de escribir (y comprender). También he resuelto esto con una implementación propia de una cola asíncrona, pero aún sería genial si hubiera una opción más estándar y mejor probada.
Por el momento, creo que ninguna colección de TPL proporciona métodos asíncronos, excepto ObservableCollection a la IU. Qué piensas ? –
Puede envolver esto en una 'Tarea task = Task.Factory.StartNew (() => {// Su código devuelve byte []});' sin embargo, esto no es sencillo y debe haber una mejor manera .. –
MoonKnight
El empaquetado de una tarea consumirá una tarea que se bloqueará en un identificador de espera. Dado que hay muchas tareas en marcha que ocuparán una tarea para siempre, lo que hará que me queden sin tareas en la piscina desafortunadamente. – Dervall