2009-04-28 16 views
0

L'ordinateur est connecté à un appareil de mesure via un COM1 physique. J'ai une forme simple où j'ouvre un port série, dire à l'appareil que je suis vivant et parfois l'appareil envoie des données. (toutes les quelques minutes)Ouverture de l'application SerialPort C#

Thread _readThread = new Thread(Read); 
SerialPort _serialPort = new SerialPort("COM1", 9600); 
_serialPort.Parity = Parity.None; 
_serialPort.DataBits = 8; 
_serialPort.StopBits = StopBits.One; 
_serialPort.Handshake = Handshake.None; 
_serialPort.DtrEnable = true; 
_serialPort.Open(); 
_readThread.Start(); 
_serialPort.Write("#listening"); 

La fonction de lecture (qui fonctionne):

public void Read() 
{ 
    string message = _serialPort.ReadLine(); 
} 

Après environ une minute l'application se bloque (même pendant le débogage). Il signale une exception ObjectDisposedException (pour le flux sous-jacent?). Le message indique que le SafeHandle a été fermé. Stack strace est ci-dessous:

à Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult (SafeFileHandle hFile, NativeOverlapped lpOverlapped, Int32 & lpNumberOfBytesTransferred, Boolean bWait) à System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent() à System.Threading.ThreadHelper.ThreadStart_Context (état d'objet) à System.Threading.ExecutionContext.Run (ExecutionContext ExecutionContext, rappel ContextCallback, état d'objet) à System.Threading.ThreadHelper.ThreadStart() *

Toutes les idées? Le problème est rapporté largement mais implique généralement que le périphérique soit physiquement détaché du PC.

+0

Je sais que la classe SerialPort a quelques problèmes avec Mono. Utilisez-vous Mono ou MS .NET? – Skurmedel

+0

MS .NET Framework 3.5 SP1 –

+0

Probablement pas une solution, mais vous appelez Write before Open. – Skurmedel

Répondre

1

Il semblait que le câble RS232 (adaptateur) provoquait les plantages du flux de port série sous-jacent. Commuté sur un câble FTDI, cela a fonctionné. Un examen du code source du .NET Framework a beaucoup aidé. Mais je pense que le ObjectDisposedException levé devrait être attrapé par le SerialPort, pas par l'utilisateur.

0

ObjectDisposedException désigne une personne appelée Dispose sur l'objet. Que faites-vous après avoir démarré le fil de lecture? Attendez-vous que le thread de lecture se termine avant de quitter le programme? Sinon, peut-être que le thread de lecture est toujours en cours d'exécution avec le programme quitte.

+0

Je ne quitte pas le programme, il court juste un puis se bloque soudainement. Je ne fais vraiment rien après cela, et il ne plante pas sur réception. Si je terminais l'application moi-même, je fermerais correctement COM1 et disposerais de tampons. –

0

J'ai eu quelque chose de semblable à moi il y a environ un an. Pour une raison quelconque, certains caractères à la fin du tampon de lecture provoqueraient la fermeture de l'interface C# vers le port série. Cela arrivait généralement quand \r\n se trouvait à la fin de la mémoire tampon, même si cela pouvait être d'autres caractères.

Terminé juste acheter une licence à une DLL de port série commerciale.

Bonne chance!

+0

pouvez-vous nous faire savoir quelle bibliothèque port série a fonctionné pour vous? – Marek

+0

@Marek Nous avons utilisé SerialNET – scraimer

1

Essayez de vérifier IsOpen avant de lire.

De même, existe-t-il une chance que l'objet contenant _serialPort ait été déréférencé et récupéré? Si vous n'accédez jamais à _serialPort à partir d'un autre thread, essayez d'en faire une variable privée dans Read().

0

Vous avez _serialPort déclaré comme SerialPort local dans le code de démarrage du thread, à quoi fait référence _serialPort dans Read()?

Essayez de créer l'objet _serialPort dans la méthode Read() pour vous assurer qu'il se trouve dans le contexte du même thread.

0

1) Thread _readThread = nouveau Thread (Read);

// is this a local definition of _readThread var in constructor? 
// if so, after some time gabbage collector clear this var from memory, a disposed object 
// shouldnot work (there is no such an object in memory). 
// The same with SerialPort local var 
// To work properly you should somewhere in class define a member 

class foo 
{ 
    // ... 
    Thread _readThread; 
    SerialPort _serialPort; 
    bool bRunningReadTrhead=false; 

    //... 

    // which is static or instanced, than 

    public foo() 
    { 
     // ... 
     _serialPort = new SerialPort("COM1", 9600); 
     _serialPort.Parity = Parity.None; 
     _serialPort.DataBits = 8; 
     _serialPort.StopBits = StopBits.One; 
     _serialPort.Handshake = Handshake.None; 
     _serialPort.DtrEnable = true; 
     _serialPort.Open(); 
     _readThread = new Thread(Read); 

     bRunningReadTrhead=true; 

     _readThread.Start(); 

     //... 
    } 

    // creates a thread which will live a long time in loop: 
    private void Read() 
    { 
     while(bRunningReadTrhead) 
     { 
      try 
      { 
       string message = _serialPort.ReadLine(); 
      } 
      catch(Exception e) 
      { 
      Console.Write(e); 
      } 
     } 

     // exits a worker thread when you set global bool in false 
    } 

    // ... 
} 

// if you do not set a loop the thread also finish all jobs and become disposed