2011-08-28 423 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因为其具有多个根,然后得到一个节点上的值每个新的split xml并通过串行发送。它在第一个分割xml上工作,并且它的节点通过串行发送,然后停止访问,在尝试将第二个节点写入串行时拒绝com端口消息。

我有另一个应用程序,我用相同的串行代码,它工作正常(我只是累了,然后关闭它。)...所以它的奇怪。

+0

也许你没有正确地关闭一些引用,并且打开accessor意味着拒绝来自同一应用/线程的更多访问? –

回答

21

您可以打开一个串行端口只有一次。但是你的代码在while循环中有Open()调用。这只适用于第一次通过循环kaboom第二次传球。 @ cdhowie的解决方案也无法正常工作,SerialPort有一个文档警告的怪癖(aka bug)。在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

除了汉斯回答:

我有同样的问题,并与开闭串行端口之间的一些睡眠时间逛了一下播放。在我的情况下,250毫秒就足够了。 也许这会帮助那里的人。

编辑:

我优化我的解决办法,这就是我想出了:

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。 我选择了这些值,因为它们在任何需要的用例中似乎足够了。