2009-10-13 10 views
49

así que sé que no se debe utilizar¿Qué hay de malo en usar Thread.Abort()

Thread.Abort() 

Pero nunca se me ha dado una buena explicación. ¿Hay una penalización de rendimiento o algo de dinero oculto?

Sé que no se puede ignorar/tragar el ThreadAbortException (que tiene sentido)

+4

Hay muchos hilos en SO: http://www.google.com/search?q=thread.abort()+site%3Astackoverflow.com – Groo

Respuesta

67

Además de todas las otras buenas respuestas aquí, permítanme agregar que no hay ninguna garantía de que una llamada a Thread.Abort realmente abortará el hilo en cuestión, nunca. Es posible (aunque no particularmente fácil) "endurecer" un hilo contra el aborto. Si, por ejemplo, está abortando un hilo porque cree que está ejecutando un código hostil, entonces el código hostil podría resistir su propia destrucción.

Si tiene una operación de larga ejecución que involucra un código que usted no posee y que debe eliminarse limpiamente, la forma correcta de hacerlo es poner ese código en su propio proceso , no en su propio hilo.(Y preferiblemente en un dominio de aplicación altamente restringido de seguridad en ese proceso). Luego puede eliminar el proceso limpiamente.

En resumen, Thread.Abort es, en el mejor de los casos, indicativo de un mal diseño, posiblemente poco fiable y extremadamente peligroso. Debe evitarse a toda costa; el único momento en el que deberías considerar abortar un hilo es mediante un código de "apagado de emergencia" en el que intentas derribar un dominio de aplicación lo más limpiamente posible.

+0

Tengo una de las situaciones que resaltas. ¿Cuál es el código de alguien más (una consola de IronPython) que tiene una función Ejecutar (...) que espera ejecutarse en un hilo. BTW, ¿Tiene un ejemplo de 'endurecimiento' de un hilo? –

+8

Realice una búsqueda web en "Regiones de ejecución restringidas" y obtendrá más información de la que desea saber acerca de cómo desordenar la propagación de excepciones de aborto de subprocesos. –

+0

¿No debería simplemente usar 'AppDomain.Unload' para derribar un dominio de la aplicación? 'AppDomain.Unload' llamará a' Thread.Abort' en todos los hilos que se ejecutan en el dominio por usted. –

2

Thread.Abort detiene el hilo de forma incontrolada. thread.Abort lanzará una excepción, lo que hará que el hilo se detenga inmediatamente.

¿Qué hay de malo en eso? En la mayoría de los casos, quiere detener con gracia la operación que está realizando. Por ejemplo, si está ejecutando una operación ACID, es posible que desee completar la operación actual antes de finalizar el hilo, para que su sistema permanezca en un estado estable.

4

Cuando llama a Thread.Abort() en otro hilo, se inyecta una ThreadAbortException en el flujo de ese hilo. Si tiene suerte, el código se manejará bien y abortará en un estado bien definido. El problema es que no tienes manera de averiguar si tendrás suerte en todos los casos, por lo que si prefieres la seguridad antes que pedir perdón a Thread. Abordar otros hilos no es una buena idea.

14

Porque si sabe que el hilo está en un estado seguro en el que puede abortarse, seguramente puede organizar una mejor comunicación y hacer que el hilo salga limpiamente.

El subproceso podría haber tenido un bloqueo y estar en el medio de cambiar algún estado compartido, y el Thread.Abort deshará el bloqueo y dejará el estado compartido dañado.

+1

Esto se puede evitar con el uso de http: // msdn. microsoft.com/en-us/library/system.threading.thread.begincriticalregion.aspx, aunque lo consideraría bastante frágil. –

+0

Es posible envolver el cuerpo de su hilo en un try/finally y limpiar sus recursos en el bloque finally. Pero, en general, veo lo que quieres decir. –

+0

@ RobFonseca-Ensor No solo es frágil. ¿Alguna vez ha intentado escribir código abort-safe? Hace que la mera seguridad de hilos parezca trivial. El 'Aborto' puede ocurrir * en cualquier lugar * (en código administrado) - incluso la propia instrucción 'lock' en realidad no es abort-safe. Así que no solo te quedaría un estado corrupto, de hecho podrías tener un 'candado' que es imposible de lanzar; se liberará cuando el hilo muera, por supuesto, pero eso no tiene que suceder nunca (hasta que el proceso muera). – Luaan

0

Thread.Abort eleva una excepción en el subproceso de destino. Mientras tanto, el hilo de destino puede estar realizando algunas operaciones críticas y el aumento de una excepción puede romper el estado de su aplicación.

5

En resumen. Cualquier objeto IDisposable no puede desecharse. Cualquier objeto bloqueado no puede ser desbloqueado. Cualquier cosa que deba ser realizada al 100% nunca se realizará.

+8

Cualquier cosa que deba ejecutarse al 100% fallará tarde o temprano debido a un corte de energía ... – gimpf

+2

Esto es incorrecto, 'Abort' ejecutará' finally' bloques y por lo tanto dispondrá 'IDisposable' también libera cualquier bloqueo debido a Misma razón. –

+0

@ByteBlast ¿Qué quieres decir? usar la declaración es irrelevante aquí. la clave es 'finalmente' se ejecutará. No importa que uses la declaración 'using' o no. –

11

Es más fácil hacer daño a sí mismo. Como otros han declarado, plantea una excepción en el código, que puede ocurrir en cualquier punto. Esto podría estar bien si espera que esto y ha codificado de manera que maneja elegantemente esta excepción en cualquier momento, pero algunas personas no:

Monitor.Enter(obj); 
// some code - if exception is raised here, then the lock isn't released 
Monitor.Exit(obj) 

IDisposable someCriticalResource = GetResource(); 
// some code - if exception is raised here, then the object isn't disposed 
someCriticalResource.Dispose(); 

Además, si está trabajando con muchas personas en un equipo a menos que tenga buena Revisiones de código no puede garantizar la calidad del código con el que trabajará. Por lo tanto es una buena idea para dar buenas gospal de "no Thread.Abort()" de lo que es hacer que la gente recuerde que debe escribir código que es robusto frente a las excepciones que ocurren en cualquier lugar dentro de ese código.

+2

Un punto importante aquí es que 'using' es * not * abort-safe tampoco; hay una (diminuta) ventana de oportunidad entre la creación de la instancia y el inicio del bloque' try-finally'. Es una gran receta para errores sutiles que nunca podrás reproducir y que puede corromper fácilmente tus datos, bloquear o matar tu aplicación, etc. – Luaan

Cuestiones relacionadas