¿Cómo borrar el ConcurrentBag? no tiene ningún método como Clearo RemoveAll...
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 _);
}
Actualización 10/03/2017: Como @Lou señala correctamente, la asignación es atómica. En este caso, la creación de ConcurrentBagno será atómica, pero poner esa referencia en la variable será atómica, por Interlocked.Exchangelo que no es estrictamente necesario bloquearla o rodearla.
Algunas lecturas adicionales:
¿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 ConcurrentBagsí mismo.
Si sabe que nada más accederá a la bolsa en este momento, alójela y reza y no la cierre :-)
bag = newcon impunidad?
Interlocked.Exchangepuede ser mejor que un candado
Interlocked.Exchangefunciona si se agrega otro hilo a la bolsa en el momento del intercambio? ¿ AddEso se bloquea durante el Exchange?
Interlocked.Exchangeson 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 hacerlo Add(T element), pero, francamente, vale la pena el tiempo ahorrado.
ConcurrentBag? No veo ninguna propiedad o método nativo para hacer eso. El Containsno cuenta. Es un método de extensión para IEnumerables 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.
A partir de .NET Core 2.0 / .NET Standard 2.1 / .NET Framework 5.0, hay un Clear()método en ConcurrentBag<T>. Consulte: ConcurrentBag.Clear .