Question

Encore une fois, je veux parler de la sécurité de la fonction Thread.Abort. Je me suis intéressé d'avoir un moyen d'interrompre les opérations que je ne peux pas vraiment contrôler et ne veulent pas vraiment, mais je veux avoir mes fils libres le plus tôt possible pour empêcher fil soif de ma demande.

J'ai donc écrit un code de test pour voir s'il est possible d'utiliser Thread.Abort et ont le fil nettoyer les ressources abandon propertly. Voici le code:

int threadRunCount = 0;
int threadAbortCount = 0;
int threadFinallyCount = 0;
int iterations = 0;

while( true )
{
 Thread t = new Thread( () =>
 {
  threadRunCount++;
  try
  {
   Thread.Sleep( Random.Next( 45, 55 ) );
  }
  catch( ThreadAbortException )
  {
   threadAbortCount++;
  }
  finally
  {
   threadFinallyCount++;
  }
 } );

 t.Start();
 Thread.Sleep( 45 );
 t.Abort();

 iterations++;
}

Alors, jusqu'à présent ce code a travaillé pendant environ 5 minutes, et threadRunCount était toujours égal à threadFinally et threadAbort était un peu plus faible en nombre, parce que certaines discussions terminées sans interruption ou probablement se sont avortés en enfin.

La question est, dois-je raté quelque chose?

Était-ce utile?

La solution

Avec un test artificiel, vous pouvez prouver quoi que ce soit.

Tout ce que vous avez prouvé est que avec le code que vous avez écrit pour votre test , Thread.Abort semble fonctionner très bien.

Mais le problème est que dès que vous commencez à utiliser les choses qui doivent être éliminés, tout espoir est perdu.

Par exemple, essayez ce code:

using (Stream stream = new FileStream(@"C:\Test.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.None))
{
    Thread.Sleep( Random.Next( 45, 55 ) );
}

Maintenant, exécutez pendant un certain temps et me dire si cela fonctionne encore.

Le problème apparaît lorsque le code a quitté votre sommeil appel, et est à l'intérieur du bloc enfin implicite pour l'utilisation de blocs, et est sur le point de fermer votre flux, puis vous l'annuler.

Le problème avec Thread.Abort est que cela peut arriver , même à l'intérieur du code qui n'est pas censé lancer des exceptions.

Par exemple, vous attendez-vous vraiment le code suivant plantage après if expression a été évaluée, mais avant l'Dispose appel est passé par?

if (_ObjectToDispose != null)
{
    _ObjectToDispose.Dispose();
    _ObjectToDispose = null;
}

Et si cela arrive juste après l'appel à .Dispose? Le champ aura toujours une valeur non nulle, ce qui pourrait conduire à des problèmes subtils ailleurs.

Et si vous faites ceci:

IDisposable objectToDispose = Interlocked.Exchange(ref _ObjectToDispose, null);
if (objectToDispose != null)
    objectToDispose.Dispose();

Avec ce code, vous prenez la valeur, il remplace par null, puis avant de se déplacer à appeler Dispose, votre ThreadAbortException arrive, qui va juste laisser l'objet.

Laissez-moi juste conduire la maison point:

  

Thread.Abort devrait jamais être utilisé, sauf dans les scénarios où vous avez besoin de mettre fin au programme (ou détruire un AppDomain personnalisé avec des fils en cours d'exécution en elle). Vous devez jamais appeler Thread.Abort puis continuer à fonctionner.

Sauf si vous devez planifier des bugs dans votre emploi du temps futur. Dans ce cas, allez-y et utiliser Thread.Abort, parce que je peux presque garantir que vous avez des problèmes.

Autres conseils

Utilisation abort fil est assez sûr. Cependant, comme mentionné par d'autres qu'un abandon de thread ne peut pas s'avortés immédiatement. Appel abort fil soulèvera un ThreadAbortException dans le fil. Pour nettoyer les ressources que vous pouvez attraper cette exception et faire les opérations de nettoyage nécessaires.

static void Run()
{
  try 
  {
    while(someCondition)
    {
       ....
       ....
       ....
       if (someOtherCondition)
          throw new ThreadAbortException("Thread aborted");
    }
  }
  catch(ThreadAbortException e)
  {
    ...
    ... //clean up resources here.
    ...
  }
  finally
  {
    ...
  }  
}

Utilisation Thread.Abort est très bien. Cependant, il ne s'interrompt pas toujours immédiatement. Si un thread est en train de faire du code non managé, il ne sera pas fait avorter jusqu'à ce qu'il retourne au code managé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top