2011-08-28 46 views
8

코드 :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(); 
} 

는, 공유 메모리를 읽고 공유 메모리는 다음 같은 파일을 XML 리더 열립니다, 파일에 씁니다과 여러 뿌리를 가지고 있기 때문에 XML을 분할 후 노드의 가치를 얻을 수 각각의 새 분할 XML 및 직렬 통해 보냅니다. 첫 번째 분할 XML에서 작동하고 노드가 직렬로 전송 된 다음 두 번째 노드를 직렬로 쓰려고 시도 할 때 COM 포트 메시지에 대한 액세스가 거부되어 중지됩니다.

나는 동일한 시리얼 코드로 만든 다른 앱을 가지고 있으며, 잘 작동한다. (나는 그저 피곤하다.) ... 그래서 이상하다.

+0

어쩌면 일부 참조가 제대로 닫히지 않았으며 접근자가 동일한 앱/스레드에서 더 많은 액세스를 거부한다는 의미입니까? –

답변

21

한 번만 직렬 포트를 열 수있는이 코드를 변경합니다. 하지만 코드에는 while 루프 안에 Open() 호출이 있습니다. 그것은 루프를 통과 한 첫 번째 패스, 2 차 패스의 kaboom에서만 작동합니다. @ cdhowie의 해결책은 작동하지 않습니다. SerialPort에는 설명서에서 경고하는 버크 (일명 버그)가 있습니다. Dispose() 또는 Close() 호출 후에 작업자 스레드가 종료되도록하려면 시간이 필요합니다. 시간의 길이는 불특정하고 예측할 수 없습니다.

진정한 솔루션은 간단합니다. while 루프 전에 Open() 호출을 이동하십시오. 한스 '대답에 추가

+0

예! 고맙습니다! – Csharpz

0

한스의 답변은이 하나를 대체합니다. 나는 상황과 정보 제공의 목적으로 만 그것을 떠난다.


포트 사용을 마친 후에는 포트를 닫아야합니다. 가비지 수집기가 다른 핸들을 열기 전에 먼저 SerialPort 개체를 수집하지 않습니다.

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

하려면 :

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

이것은 SerialPort가 이상하지 않습니다. –

+0

흠, 그건 재미 있어요. 나는 정보를 제공하기 위해 내 대답을 떠날 것입니다. – cdhowie

2

:

은 저도 같은 문제를 겪고 개방 및 직렬 포트를 닫는 사이에 수면 시간과 약간의 주위했다. 내 경우에는 250ms면 충분했다. 어쩌면 이것이 누군가를 도울 것입니다.

편집 :

나는 내 솔루션을 최적화하고 이것이 내가 생각 해낸 것입니다 :

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); 
    } 
} 

당신은 sleepTimeInMs 및/또는 maxRetries 함께 놀러 수 있습니다. 필자는 필 요한 사용 사례에서 충분하다고 생각했기 때문에이 값을 선택했습니다.

관련 문제