почему доступ к com-порту запрещен? - PullRequest
11 голосов
/ 28 августа 2011

код:

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 reader и разбивает xml, так как он имеет несколько корней, затем получает значение узла в каждом новом разделенном xml и отправляет по последовательному каналу. он работает с первым разделенным XML и его узел отправляется через последовательный порт, а затем останавливается, когда доступ к сообщению com-порта запрещен при попытке записи второго узла в последовательный порт.

У меня есть другое приложение, которое я сделал с тем же серийным кодом, и оно работает нормально (я просто устал, потом закрыл его) ... так странно.

Ответы [ 5 ]

25 голосов
/ 28 августа 2011

Вы можете открыть последовательный порт только один раз.Но ваш код имеет вызов Open () внутри цикла while.Это будет работать только для первого прохода через цикл, kaboom на 2-й проход.Решение @ cdhowie также не работает, SerialPort имеет причуду (иначе ошибку), о которой предупреждает документация.Необходимо время, чтобы рабочий поток мог выйти после вызовов Dispose () или Close ().Количество времени не определено и непредсказуемо.

Реальное решение простое, просто переместите вызов Open () перед циклом while.

3 голосов
/ 15 июня 2016

В дополнение к ответу Ганса:

У меня была та же проблема, и я немного поиграл с некоторым временем ожидания между открытием и закрытием последовательного порта.В моем случае 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.Я выбрал эти значения, потому что они казались достаточными для любого необходимого варианта использования.

0 голосов
/ 03 июля 2019

Вам необходимо закрыть и утилизировать порт, если он открыт, потому что он не был удален при последнем подключении.

0 голосов
/ 15 марта 2019

Решение, которое сработало для меня, заключается в следующем: 1: используйте try catch block и поместите в него весь код открытия и закрытия порта.

2: Используйте функцию IsOpen (), чтобы проверить, является ли портуже открыт или нет.

3: Если возникает какое-либо исключение (доступ запрещен), напишите код Port.Close () в блоке перехвата, чтобы освободить этот порт.

4: Сделать объектпоследовательного порта перед попыткой перехватить блок, чтобы сделать его универсальным.

5: вызов Open () не должен быть внутри цикла.Вы должны открыть порт только один раз, а после цикла вы должны закрыть его.

Если вы выполните все эти шаги, вы никогда больше не столкнетесь с этой проблемой.

Пример кода приведен ниже:

GsmCommMain comm = new GsmCommMain(COMPort.ToString(), 9600, 500);

try{ for (int i = 0; i < dtObj.Rows.Count; i++)
                                    {
                                        if (dtObj.Rows[i]["smsNumber"] != null)
                                        {
                                            if (dtObj.Rows[i]["smsNumber"].ToString() != "")
                                            {
                                                if (dtObj.Rows[i]["status"].ToString() != "Sent")
                                                {
                                                    Thread.Sleep(Convert.ToInt32("50000"));
                                                    string txtMessage = dtObj.Rows[i]["sms"].ToString();
                                                    string txtDestinationNumbers = dtObj.Rows[i]["smsNumber"].ToString();
                                                    bool unicode = true;
                                                    SmsSubmitPdu[] pdu = SmartMessageFactory.CreateConcatTextMessage(txtMessage, unicode, txtDestinationNumbers);
                                                    comm.SendMessages(pdu);
                                                    obj_bal_ForAll.bal_forAll_Delete("tbl_SMS", "smsId", dtObj.Rows[i]["smsId"].ToString());
                                                }
                                            }
                                        }
                                    }
                                    if (comm.IsOpen())
                                    {
                                        comm.Close();
                                    }  
                                    }catch(Exception ex){if (comm.IsOpen()){comm.Close();}}
0 голосов
/ 28 августа 2011

ответ Ганса заменяет этот; Я оставляю это только для контекста и в информационных целях.


Вам нужно закрыть порт, когда вы закончите с ним. Сборщик мусора не собирает первый объект 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() + ",");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...