2011-08-28 26 views
8

el código:¿por qué se niega el acceso al puerto com?

static void Main(string[] args) 
{ 
    Console.WriteLine("Memory mapped file reader started"); 

    using (var file = MemoryMappedFile.OpenExisting("AIDA64_SensorValues")) 
    { 
     using (var readerz = file.CreateViewAccessor(0, 0)) 
     { 
      var bytes = new byte[567]; 
      var encoding = Encoding.ASCII; 
      readerz.ReadArray<byte>(0, bytes, 0, bytes.Length); 

      File.WriteAllText("C:\\myFile.txt", encoding.GetString(bytes)); 

      var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment }; 
      using (var reader = XmlReader.Create("C:\\myFile.txt", readerSettings)) 
      { 
       while (reader.Read()) 
       { 
        using (var fragmentReader = reader.ReadSubtree()) 
        { 
         if (fragmentReader.Read()) 
         { 

          reader.ReadToFollowing("value"); 
          SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One); 
          port.Open(); 
          port.Write(reader.ReadElementContentAsString() + ","); 
         } 
        } 
       } 
      }  
     } 
    } 

    Console.WriteLine("Press any key to exit ..."); 
    Console.ReadLine(); 
} 

se lee la memoria compartida, escribe que la memoria compartida para presentar, a continuación, el mismo archivo se abre con lector de XML y se divide xml ya que tiene múltiples raíces, a continuación, obtiene el valor de un nodo en cada nuevo xml dividido y envía por serie. funciona en el primer xml dividido y su nodo se envía a través de una serie, luego se detiene con un acceso denegado al mensaje de puerto en el intento de escribir el segundo nodo en la serie.

tengo otra aplicación que hice con el mismo código de serie y funciona bien (me cansé y luego la cerré) ... así que es extraño.

+0

tal vez no está cerrando algunas referencias correctamente y abrió el acceso significa que se le negará más acceso desde la misma aplicación/hilo. –

Respuesta

21

Puede abrir un puerto serie sólo una vez. Pero su código tiene la llamada Open() dentro del ciclo while. Eso solo funcionará para el primer pase a través del ciclo, kaboom en el segundo pase. La solución de @ cdhowie tampoco funciona, SerialPort tiene una peculiaridad (error conocido) de la que la documentación advierte. Necesita tiempo para permitir que un trabajador salga después de la llamada Dispose() o Close(). La cantidad de tiempo no está especificada e es impredecible.

La solución real es simple, solo mueva la llamada Open() antes del ciclo while.

+0

¡SÍ! ¡gracias! – Csharpz

0

La respuesta de Hans supera a esta; Lo dejo solo por contexto e información.


Debe cerrar el puerto cuando haya terminado con él. El recolector de elementos no utilizados no está recopilando el primer objeto SerialPort antes de intentar abrirlo. Cambiar este código:

SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One); 
port.Open(); 
port.Write(reader.ReadElementContentAsString() + ","); 

Para:

using (SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One))) 
{ 
    port.Open(); 
    port.Write(reader.ReadElementContentAsString() + ","); 
} 
+3

Esto tampoco funciona, SerialPort quirk. –

+0

Hmm, eso es interesante. Dejo mi respuesta por razones informativas. – cdhowie

2

Además de la respuesta de Hans:

que tenían el mismo problema y jugar un poco con algunas horas de sueño entre la apertura y cierre del puerto serie. En mi caso, 250 ms fueron suficientes. Quizás esto ayude a alguien por ahí.

EDIT:

que optimiza mi solución y esto es lo que ocurrió:

int maxRetries = 20; 
const int sleepTimeInMs = 50; 
string loggingMessage = string.Empty; 

while (maxRetries > 0) 
{ 
    try 
    { 
     loggingMessage = "Opening serial port '" + mSerialPort.PortName + "'..."; 
     mSerialPort.Open(); 
     loggingMessage += "Succeeded."; 
     IOLogger.LogInfo(loggingMessage); 
    } 
    catch (UnauthorizedAccessException unauthorizedAccessException) 
    { 
     maxRetries--; 
     loggingMessage += "Failed (UnauthorizedAccessException): "; 
     IOLogger.LogError(string.Format(loggingMessage + unauthorizedAccessException.Message + " -> Retrying in about {0} milliseconds...", sleepTimeInMs)); 
     Thread.Sleep(sleepTimeInMs); 
    } 
    catch (Exception exception) 
    { 
     loggingMessage += "Failed: "; 
     IOLogger.LogError(loggingMessage + exception.Message); 
    } 
} 

Puede jugar con el sleepTimeInMs y/o la maxRetries. He elegido esos valores porque parecían ser suficientes en cualquier caso de uso necesario.

Cuestiones relacionadas