为什么访问com端口被拒绝?

Csh*_*rpz 11 c# xml serial-port

代码:

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();
}
Run Code Online (Sandbox Code Playgroud)

它读取共享内存,将共享内存写入文件,然后使用xml reader打开同一文件并拆分xml,因为它有多个根,然后获取每个新拆分xml上的节点值并通过串行发送.它适用于第一个拆分xml,并且其节点通过串行发送然后停止,并且在尝试将第二个节点写入串行时拒绝访问com端口消息.

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

Han*_*ant 26

您只能打开一次串口.但是你的代码在while循环中有Open()调用.这只适用于第一次通过循环,kaboom在第二次传球.@ cdhowie的解决方案也不起作用,SerialPort有一个文档警告的怪癖(也就是bug).在Dispose()或Close()调用之后,需要时间让工作线程退出.时间量未指定且不可预测.

真正的解决方案很简单,只需在while循环之前移动Open()调用即可.


M. *_*ner 5

除了汉斯的回答之外:

我遇到了同样的问题,并在打开和关闭串行端口之间玩了一些睡眠时间。就我而言,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);
        break;
    }
    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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用sleepTimeInMs和/或maxRetries。我选择这些值是因为它们似乎足以满足任何需要的用例。