[英]why is access to com port denied?
代碼:
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 端口消息。
我有另一個使用相同序列代碼制作的應用程序,它運行良好(我只是累了然后關閉了它。)...所以很奇怪。
您只能打開一個串行端口一次。 但是您的代碼在 while 循環中具有 Open() 調用。 這僅適用於第一次通過循環,第二次通過的 kaboom。 @cdhowie 的解決方案也不起作用,SerialPort 有一個文檔警告的怪癖(又名錯誤)。 在 Dispose() 或 Close() 調用之后讓工作線程退出需要時間。 時間量是未指定和不可預測的。
真正的解決方案很簡單,只需在 while 循環之前移動 Open() 調用即可。
除了漢斯的回答:
我遇到了同樣的問題,在打開和關閉串行端口之間有一些睡眠時間。 在我的情況下,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
。 我選擇這些值是因為它們在任何需要的用例中似乎都足夠了。
如果端口打開,您需要關閉並處理它,因為他沒有在最后一次連接時處理。
對我有用的解決方案如下: 1:使用try catch塊並將打開和關閉端口的所有代碼放入其中。
2:使用 IsOpen() 函數檢查端口是否已經打開。
3:如果發生任何異常(訪問被拒絕),請在 catch 塊中寫入 Port.Close() 代碼以釋放該端口。
4:在try catch塊之前先制作串口對象,使其通用。
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();}}
漢斯的回答取代了這一回答; 我將其僅用於上下文和信息目的。
完成后,您需要關閉該端口。 在您嘗試打開另一個句柄之前,垃圾收集器不會收集第一個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() + ",");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.