Почему запрещен доступ к 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, так как он имеет несколько корней, затем получает значение node в каждом новом расклассифицированном xml и отправляет его последовательный. он работает с первым разделенным xml, а его node отправляется по последовательному, а затем останавливается, когда доступ запрещен к сообщению COM-порта при попытке записать второй node в последовательный.
У меня есть другое приложение, которое я сделал с тем же серийным кодом, и он отлично работает (я просто устал, а затем закрыл его.)... так странно.
Ответы
Ответ 1
Вы можете открыть последовательный порт только один раз. Но ваш код имеет вызов Open() внутри цикла while. Это будет работать только для первого прохода через петлю, kaboom на втором проходе. Решение @cdhowie тоже не работает, у SerialPort есть причуда (ака ошибка), о которой предупреждает документация. Для вызова рабочего потока после вызова Dispose() или Close() требуется время. Количество времени неуказано и непредсказуемо.
Реальное решение простое, просто переместите вызов Open() до цикла while.
Ответ 2
В дополнение к ответу Ганса:
У меня была такая же проблема, и я немного поиграл с некоторым временем сна между открытием и закрытием последовательного порта. В моем случае было достаточно 250 мс.
Может быть, это поможет кому-то там.
EDIT:
Я оптимизировал свое решение, и вот что я придумал:
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
.
Я выбрал эти значения, потому что они, казалось, были достаточными в любом случае использования.
Ответ 3
Ответ Ганса отменяет это; Я оставляю его только для контекстных и информационных целей.
Вам нужно закрыть порт, когда вы закончите с ним. Сборщик мусора не собирает первый объект SerialPort
, прежде чем пытаться открыть ему другой дескриптор. Измените этот код:
SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
port.Open();
port.Write(reader.ReadElementContentAsString() + ",");
To:
using (SerialPort port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One)))
{
port.Open();
port.Write(reader.ReadElementContentAsString() + ",");
}
Ответ 4
Решение, которое сработало для меня, заключается в следующем: 1: используйте блок try catch и вставьте в него весь код открытия и закрытия порта.
2: Используйте функцию IsOpen(), чтобы проверить, открыт ли порт или нет.
3: Если возникает какое-либо исключение (доступ запрещен), напишите код Port.Close() в блоке catch, чтобы освободить этот порт.
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();}}
Ответ 5
Вам нужно закрыть и утилизировать порт, если он открылся, потому что он не утилизируется при последнем подключении.