¿Cómo borrar el ConcurrentBag
? no tiene ningún método como Clear
o RemoveAll
...
c#
concurrency
PawanS
fuente
fuente
Respuestas:
Aunque puede que no esté completamente claro debido a una posible condición de carrera, esto es suficiente:
while (!myBag.IsEmpty) { myBag.TryTake(out T _); }
fuente
Actualización 10/03/2017: Como @Lou señala correctamente, la asignación es atómica. En este caso, la creación de
ConcurrentBag
no será atómica, pero poner esa referencia en la variable será atómica, porInterlocked.Exchange
lo que no es estrictamente necesario bloquearla o rodearla.Algunas lecturas adicionales:
La asignación de referencia es atómica, entonces, ¿por qué se necesita Interlocked.Exchange (ref Object, Object)?
¿Es una tarea de referencia segura para subprocesos?
Siempre puede bloquear el acceso a la bolsa y crear una nueva instancia de la misma. Los artículos en la bolsa serán elegibles para GC si nada más los está reteniendo:
lock (something) { bag = new ConcurrentBag(); }
O como señala Lukazoid:
var newBag = new ConcurrentBag(); Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);
Sin embargo, una manera fácil de agrupar el contenido, asume que siempre que un elemento desea acceder, también obtiene el bloqueo; esto podría ser costoso y podría anular el ajuste de rendimiento que se ha realizado en
ConcurrentBag
sí mismo.Si sabe que nada más accederá a la bolsa en este momento, alójela y reza y no la cierre :-)
fuente
bag = new
con impunidad?Interlocked.Exchange
puede ser mejor que un candadoInterlocked.Exchange
funciona si se agrega otro hilo a la bolsa en el momento del intercambio? ¿Add
Eso se bloquea durante elExchange
?Interlocked.Exchange
son redundantes aquí (y no proporcionan seguridad para subprocesos).La respuesta seleccionada es una especie de, bueno, una solución alternativa, así que estoy agregando mi propia solución.
Mi solución fue mirar todas las colecciones disponibles en el espacio de nombres System.Collections.Concurrent para encontrar una en la que fuera trivial borrar todos los elementos de la colección.
La clase ConcurrentStack tiene un método Clear () que elimina todos los elementos de la colección. De hecho, es la única colección en el espacio de nombres (actualmente) que lo hace. Sí, tiene que
Push(T element)
hacerlo en lugar de hacerloAdd(T element)
, pero, francamente, vale la pena el tiempo ahorrado.fuente
ConcurrentBag
? No veo ninguna propiedad o método nativo para hacer eso. ElContains
no cuenta. Es un método de extensión paraIEnumerable
s genéricos , y es todo menos eficiente.En el espíritu de las soluciones ...
ConcurrentDictionary<T, bool>
tiene un Clear atómico, pero también le permite comprobar rápidamente si existe una clave. 'Rápido' es un término relativo, por supuesto, pero dependiendo de su uso, puede ser más rápido que enumerar una pila grande.fuente
A partir de .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0, hay un
Clear()
método enConcurrentBag<T>
. Consulte: ConcurrentBag.Clear .fuente
int cnt = _queue.Count; for (; cnt > 0; cnt--) { _queue.TryDequeue(out img); }
No cae en un bucle infinito y borra el contenido del tiempo presente.
fuente