Je suppose que c'est parce que vous utilisez Thread.Abort pour terminer le thread - ce qui est généralement mal vu. Le comportement du thread lorsque vous abandonner il n'est pas prévisible. Pour cette raison, étant donné que le port série est un wrapper sur du code natif, il existe des ressources natives - représentées par un SafeHandle dans .NET - qui sont éliminées de manière inattendue et vous obtenez ainsi l'exception.
Vous pouvez penser à ce qui se passe avec votre fil comme ceci:
- vous démarrez votre fil
- vous ouvrez le port série (qui alloue les ressources indigènes et utilise SafeHandle (s) pour conserver les ressources)
- vous commencez à lire à partir du port série
- puis à un moment donné (inattendu à votre fil) vous appelez Thread.Abort sur elle
- très probablement le code dans votre fil est à tha point t essayer d'accéder au port série (pour lire les données)
- le fil est tué et la poignée de port série est détruit implicitement
- vous obtenez une exception levée à partir du code dans la fonction ReadLine() du port série, car le handle dont il disposait n'est plus valide
Vous devriez vraiment utiliser une méthode différente pour abandonner le thread afin d'avoir une chance de fermer et d'éliminer le port série.
Une bonne façon de fermer votre fil pourrait être mis en œuvre en utilisant un ManualResetEvent comme ceci:
protected ManualResetEvent threadStop = new ManualResetEvent(false);
protected void ReadData()
{
SerialPort serialPort = null;
try
{
serialPort = SetupSerialPort(_serialPortSettings);
serialPort.Open();
string data;
while (serialPort.IsOpen)
{
try
{
data = serialPort.ReadLine();
if (data.Length > 0)
ReceivedData(serialPort, new ReceivedDataEventArgs(data));
}
catch (TimeoutException)
{
// No action
}
// WaitOne(0) tests whether the event was set and returns TRUE
// if it was set and FALSE otherwise.
// The 0 tells the manual reset event to only check if it was set
// and return immediately, otherwise if the number is greater than
// 0 it will wait for that many milliseconds for the event to be set
// and only then return - effectively blocking your thread for that
// period of time
if (threadStop.WaitOne(0))
break;
}
}
catch (Exception exc)
{
// you can do something here in case of an exception
// but a ThreadAbortedException should't be thrown any more if you
// stop using Thread.Abort and rely on the ManualResetEvent instead
}
finally
{
if (serialPort != null)
serialPort.Close();
}
}
protected void Stop()
{
// Set the manual reset event to a "signaled" state --> will cause the
// WaitOne function to return TRUE
threadStop.Set();
}
Bien sûr, lorsque vous utilisez la méthode des événements pour arrêter le fil que vous devez être pris soin d'inclure un événement état vérifier dans toutes vos longues boucles ou tâches en cours. Si vous ne voyez pas votre thread peut sembler ne pas répondre à votre réglage de l'événement - jusqu'à ce qu'il sorte de la boucle de longue durée, ou une tâche et obtient une chance de "voir" que l'événement a été défini.
J'ai ajouté un exemple de code –