gpt4 book ai didi

c# - serialport 响应 EventHandler,但不响应 ReadExisting 或 ReadLine?

转载 作者:太空狗 更新时间:2023-10-29 23:17:46 25 4
gpt4 key购买 nike

我有一个程序可以从 C# 中的串口读取数据。我需要快速写入一个端口,从中读取,然后关闭它。我不能让它打开。我知道串行端口读取和写入速度很慢,我尝试将 ReadTimeout 和 WriteTimeout 属性设置为高,并添加了一个 thread.Sleep 以尝试将设备的读取和写入时间拖出。这是一些代码:

我写入端口的方法:

    private void CheckPorts(string testMessage)
{

foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
if (testSerial.IsOpen)
{
testSerial.Close();
}
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 1000;
testSerial.Open();
if (testSerial.IsOpen)
{
string received;
testSerial.DiscardInBuffer();
try
{
//testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

testSerial.Write(testMessage);
System.Threading.Thread.Sleep(2000);

received = testSerial.ReadExisting(); //EITHER I USE THIS OR EVENT HANDLER, NOT BOTH
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}

if (received.Length > 0)
{
MessageReceived(received);
}
testSerial.Close();
}
}
}



private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string received = testSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.IndexOf("\r");
}

if (testSerial.IsOpen)
{
testSerial.Close();
}

}

我想知道,如果我绝对必须使用数据处理程序,我如何保持串行端口打开足够长的时间以从中读取数据,但在需要打开下一个端口之前关闭串行端口?

看,第一个方法被调用了几次,它遍历了一个 foreach 循环,尝试在几个端口上发送消息,然后尝试读取响应。所以,在某些时候我必须关闭端口,否则下次它通过它时,它不能正常工作,因为端口仍然打开

这是我更新后的代码(仍然无法使用):

 private void CheckPorts(string testMessage, int baudRate)
{

foreach (string s in SerialPort.GetPortNames())
{
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;

if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?

testSerial.Dispose();
timer.Dispose();
};

portNumber = Int32.Parse(s.Remove(0, 3));
testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
testSerial.ReadTimeout = 2000;
testSerial.WriteTimeout = 2000;
if (testSerial.IsOpen)
{
testSerial.Close();
}

testSerial.Open();
timer.Enabled = true;

if (testSerial.IsOpen)
{
string received;
//testSerial.DiscardInBuffer();
//autoEvent = new AutoResetEvent(false);
try
{
// testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

// autoEvent.Reset();
lblPortNum.Content = s;
lblPortNum.Refresh();

testSerial.Write(testMessage);
//System.Threading.Thread.Sleep(2000);

//testSerial.NewLine = "\r\n";
byte[] rBuff = new byte[2];
int rCnt = testSerial.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);



//received = testSerial.ReadLine();
}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}

if (received.Length > 0)
{
MessageReceived(received, Int16.Parse(s.Remove(0, 3)));
}
/*
if (autoEvent.WaitOne(2000))
{
// the port responded
// testSerial.Close();
autoEvent.Dispose();
lblPortNum.Content = "HEY I RESPONDED";
}
else
{
testSerial.Close();
autoEvent.Dispose();
continue;
// port did not respond within 2 seconds
}*/
//testSerial.Close();
}
}
}

再次更新(仍然无法正常工作)

private void CheckPorts(string testMessage, int baudRate)
{

foreach (string s in SerialPort.GetPortNames())
{
portNumber = Int32.Parse(s.Remove(0, 3));

// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}

// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;

if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?

serialOneOfMany.Dispose();
timer.Dispose();
};

if (serialOneOfMany.IsOpen)
{
string received;

try
{
lblPortNum.Content = s;
lblPortNum.Refresh();

serialOneOfMany.Write(testMessage);
byte[] rBuff = new byte[2];
int rCnt = serialOneOfMany.Read(rBuff, 0, 2);
System.Text.Encoding enc = System.Text.Encoding.ASCII;
received = enc.GetString(rBuff);

}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}

if (received.Length > 0)
{
CheckIfTheMessageMatches(received, Int16.Parse(s.Remove(0, 3)));
}

}
}

}

所以在这个更新中,它只是通过代码,我可以逐行通过代码,但它不会停止 3 秒。如果我在没有任何调试中断的情况下运行它,它只会在几分之一秒内通过它

11 月 25 日更新

 private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
string received = "";
testSerial = new SerialPort(s,baudRate, Parity.None, 8, StopBits.One);

lblStatus.Content = "Scanning...";
lblStatus.Refresh();

if (testSerial.IsOpen)
{
testSerial.Close();
}
else
{
testSerial.Open();
}

if (testSerial.IsOpen)
{
try
{
testSerial.NewLine = "\r";
lblPortNum.Content = s;
lblPortNum.Refresh();
testSerial.WriteTimeout= 500;
testSerial.ReadTimeout = 1000;
testSerial.WriteLine(testMessage);

System.Threading.Thread.Sleep(500);

/*THIS DOESN'T WORK
byte[] buffer = new byte[testSerial.BytesToRead];
int rCnt = testSerial.Read(buffer, 0, buffer.Length);
received = enc.GetString(buffer);*/

//received = Convert.ToString(testSerial.BaseStream.Read(buffer, 0, (int)buffer.Length));


received = testSerial.ReadLine();


int y = received.IndexOf("\r");
while (y == -1)
{
received = received + testSerial.ReadExisting();
y = received.Length;
}

if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
received = received + lblInfo.Content;
lblInfo.Content = received;
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (testSerial.IsOpen)
{
testSerial.Close();
}

/*I USE THIS WITH THE sPort.Read() METHOD
while (rCnt > 0)
{
if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
CheckIfTheMessageMatches(received, s);
rCnt = 0;
received = received + lblInfo.Content;
lblInfo.Content = received;
}

else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
}
*/

if (testSerial.IsOpen)
{
testSerial.Close();
}

}
catch (TimeoutException e)
{
testSerial.Close();
continue;
}
received = null;
}
}

lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}

更新代码这是一些新代码,仍然无法正常工作,甚至没有调用 dataeventhandler 一次。我知道它正在接收消息,因为我有另一个与串行设备一起使用的程序

private void CheckPorts(string testMessage, int baudRate)
{
foreach (string s in SerialPort.GetPortNames())
{
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 700;
serialOneOfMany.WriteTimeout = 100;

var interval = 500; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;

if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?

serialOneOfMany.Dispose();
timer.Dispose();
};
timer.Enabled = true;

lblStatus.Content = "Scanning...";
lblStatus.Refresh();

if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}
else
{
serialOneOfMany.Open();
}

if (serialOneOfMany.IsOpen)
{
string received;

try
{
lblPortNum.Content = s;
lblPortNum.Refresh();

serialOneOfMany.WriteLine(testMessage);
System.Threading.Thread.Sleep(400);
serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

}
catch (TimeoutException e)
{
serialOneOfMany.Close();
continue;
}
}
}

lblStatus.Content = "Finished Scanning.";
lblPortNum.Content = "";
}

private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort receivingSerial = sender as SerialPort;
string received = receivingSerial.ReadExisting();
int y = received.IndexOf("\r");
while (y == -1)
{
received = received + receivingSerial.ReadExisting();
y = received.IndexOf("\r");
}

if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
{
string name = receivingSerial.PortName;
received = received + lblInfo.Content;
lblInfo.Content = received;
CheckIfTheMessageMatches(received, name);
}
else
{
lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
}
if (receivingSerial.IsOpen)
{
receivingSerial.Close();
}

}

最佳答案

您应该能够同时执行这些操作(假设没问题)。然后,您将在引发 DataReceived 事件(删除无关代码)时关闭它们。只是不要关闭 CheckPorts 中的端口。

private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort localSerialPort = sender as SerialPort;

... // use localSerialPort instead of global/class variable

if (localSerialPort.IsOpen)
{
localSerialPort.Close();
}
}

编辑:回应评论。

您可以随时添加一个计时器。如果你把它放在 foreach 循环中,你会为每个串行端口获得一个计时器,该计时器将在 3 秒后处理其给定的串行端口。在 foreach 循环中声明计时器在这里很重要。

var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o,e) =>
{
timer.Enabled = false;

if (testSerial.IsOpen)
testSerial.Close(); // may not be necessary with Dispose?

testSerial.Dispose();
timer.Dispose();
}

timer.Enabled = true;

编辑:代码已更新,所以我会更新

范围对于我提供的代码非常重要。您应该摆脱非本地 testSerial 或在此处使用完全不同的名称。

        portNumber = Int32.Parse(s.Remove(0, 3));

// MUST BE LOCAL
var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
serialOneOfMany.ReadTimeout = 2000;
serialOneOfMany.WriteTimeout = 2000;
if (serialOneOfMany.IsOpen)
{
serialOneOfMany.Close();
}

// timer must be defined _after_ serialOneOfMany
var interval = 3000; // ms
var timer = new System.Timers.Timer(interval);
timer.Elapsed += (o, e) =>
{
timer.Enabled = false;

if (serialOneOfMany.IsOpen)
serialOneOfMany.Close(); // may not be necessary with Dispose?

serialOneOfMany.Dispose();
timer.Dispose();
};

关于c# - serialport 响应 EventHandler,但不响应 ReadExisting 或 ReadLine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7572596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com