Una y otra vez me encuentro teniendo que escribir versiones seguras para subprocesos de BindingList y ObservableCollection porque, cuando están vinculados a la interfaz de usuario, estos controles no se pueden cambiar desde varios subprocesos. Lo que trato de entender es por qué este es el caso - ¿es un error de diseño o es este comportamiento intencional?¿Por qué las clases como BindingList o ObservableCollection no son seguras para subprocesos?
Respuesta
El problema es diseñar una colección segura para subprocesos no es simple. Claro que es lo suficientemente simple como para diseñar una colección que se puede modificar/leer de múltiples hilos sin corromper el estado. Pero es mucho más difícil diseñar una colección que se pueda usar dado que se actualiza a partir de múltiples hilos. Tome el siguiente código como un ejemplo.
if (myCollection.Count > 0) {
var x = myCollection[0];
}
Supongamos que myCollection es una colección segura para la secuencia de comandos donde las adiciones y actualizaciones garantizan la no alteración del estado. Este código no es seguro para subprocesos y es una condición de carrera.
¿Por qué? Aunque myCollection es seguro, no hay garantía de que no se produzca un cambio entre las dos llamadas a myCollection: countly named y el indexador. Otro hilo puede entrar y eliminar todos los elementos entre estas llamadas.
Este tipo de problema hace que el uso de una colección de este tipo sea francamente una pesadilla. Nunca puede permitir que el valor de retorno de una llamada influya en una llamada posterior en la colección.
EDITAR
amplié esta discusión en un reciente post: http://blogs.msdn.com/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx
Para añadir un poco a la excelente respuesta de Jared: hilo de seguridad no viene de forma gratuita. Muchas (¿la mayoría?) Colecciones solo se usan en un solo hilo. ¿Por qué esas colecciones tienen penalizaciones de rendimiento o funcionalidad para hacer frente al caso de subprocesos múltiples?
Bueno, tal vez debería volver a expresarlo entonces: ¿por qué la estructura no proporciona una ThreadSafeObservableCollection o algo así? –
Esa es una pregunta más razonable, pero luego la respuesta de Jared entra en acción. Realmente depende de lo que quiere decir con "hilo seguro", que no es un simple indicador de sí/no. –
Si quiere volverse loco - here's a ThreadedBindingList<T>
que hace que las notificaciones vuelvan a aparecer automáticamente en el hilo de la interfaz de usuario. Sin embargo, todavía sería seguro para un hilo hacer actualizaciones, etc. a la vez.
Esta implementación solo calcula 'agrega' a la cadena de contexto de sincronización: no protege contra un número de otras condiciones de carrera y/o errores modificados de colección al enumerar la lista. – piers7
La recopilación de las ideas de todas las otras respuestas, creo que esta es la forma más sencilla de resolver sus problemas:
cambiar la pregunta de: "¿Por qué no es la clase X cuerdo"
a
"¿Cuál es la manera sensata de hacer esto con la clase X?"
en el constructor de la clase, obtener el displatcher actual a medida que crea sus colecciones observables. Porque, como ha señalado, la modificación necesaria para debe realizarse en el original, que puede no ser el principal hilo GUI. Así que App.Current.El despachador no es el correcto, y no todas las clases tienen un this.Dispatcher.
_dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher; _data = new ObservableCollection<MyDataItemClass>();
Utilice el despachador para invocar sus secciones de código que necesita el hilo original.
_dispatcher.Invoke(new Action(() => { _data.Add(dataItem); }));
Que debe hacer el truco para usted. Aunque hay situaciones, puede preferir . BeginInvoke en lugar de . Invoque.
- 1. ¿Las clases de singleton son seguras para subprocesos en IIS?
- 2. ¿Las propiedades estáticas autoejecutadas por C# son seguras para subprocesos?
- 3. Por qué las colecciones concurrentes de Java son realmente seguras para subprocesos
- 4. ¿Las funciones de tiempo de MSVC son seguras para subprocesos?
- 5. diferencia entre ObservableCollection y BindingList
- 6. por qué no BindingList en WPF
- 7. ¿Las ventanas Win32 son seguras?
- 8. ¿Están seguras las clases de Static?
- 9. ObservableCollection (Of T) vs BindingList (Of T)?
- 10. ¿Por qué std :: queue :: empty() no es seguro para subprocesos? ¿Las funciones de const no deberían ser seguras para hilos?
- 11. ¿Las segmentaciones de C# son seguras?
- 12. ¿Por qué los servlets no son seguros para subprocesos?
- 13. ¿Las matrices C# son seguras?
- 14. ¿Las engas C# son seguras?
- 15. ¿Las funciones en línea en C/C++ son una forma de hacerlas seguras para subprocesos?
- 16. ¿Las variables estáticas de la función son seguras para subprocesos en GCC?
- 17. ¿Por qué ObservableCollection no admite cambios masivos?
- 18. ¿Por qué algunos objetos no son accesibles desde diferentes subprocesos?
- 19. cuán seguras son las declaraciones preparadas por PDO
- 20. ¿Qué operaciones en el nodo son seguras para hilos?
- 21. ¿Qué operaciones son seguras para hilos en std :: map?
- 22. ¿Son seguras las consultas multilínea sql-injection?
- 23. ¿Qué tan seguras son las sesiones de PHP?
- 24. Custom ObservableCollection <T> o BindingList <T> con soporte para notificaciones periódicas
- 25. WPF ObservableCollection <T> vs BindingList <T>
- 26. ¿Por qué las interfaces no son [Serializable]?
- 27. ¿Qué tan seguras son las claves de acceso Amazon AWS?
- 28. ¿Los métodos estáticos en las clases de código subyacente de ASP.NET no son seguros para subprocesos?
- 29. ¿Por qué todas las clases anónimas son implícitamente finales?
- 30. Java: ¿Por qué son necesarias las clases de contenedor?
Tengo exactamente el mismo problema. ¿Cómo uso Dispatcher o si no agrego un elemento a mi BindingList desde un hilo de fondo? – Houman
Sí, en resumen, el diseño de .NET collection * interfaces * no es apropiado para la seguridad de subprocesos. Como señala Jared, por ejemplo, la propiedad Count es inútil en un entorno de subprocesos múltiples. –
Hay muchos subconjuntos útiles de la funcionalidad 'IList' que podrían implementarse de manera segura para hilos. Los elementos que eliminan cosas o mueven cosas serían problemáticos, pero el resto de la interfaz sería un subconjunto útil para muchas aplicaciones. Sería útil una versión de 'Add' que informara el índice del elemento agregado, pero no todas las aplicaciones lo necesitarían. Si cada elemento que se agrega continuará existiendo en la misma ranura durante la vida útil de la lista, una implementación 'IList ' sin hilos podría ser útil en muchos escenarios de subprocesos múltiples sin bloqueo externo. –
supercat