Событие DataReceived
может возникать в середине строки, и вы, возможно, еще не получили сообщение целиком.Вам нужно будет знать, что вы ищете, как правило, перевод строки (LF) или возврат каретки (CR).Я использую StringBuilder
для построения своих строк, ниже приведен пример, где LF означает, что я получил все сообщение.Я добавляю символы в свою строку, пока не узнаю, что у меня есть целое сообщение.Я быстро очищаю буфер, потому что ваша следующая строка может появиться во время оценки.В этом простом примере я просто вызываю функцию для оценки моей строки, но вы можете использовать делегата здесь.
StringBuilder sb = new StringBuilder();
char LF = (char)10;
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
foreach (char c in Data)
{
if (c == LF)
{
sb.Append(c);
CurrentLine = sb.ToString();
sb.Clear();
//do something with your response 'CurrentLine'
Eval_String(CurrentLine);
}
else
{
sb.Append(c);
}
}
}
Как только вы получите сообщение целиком, вы сможете оценить его для того, что вам нужно.,Я не уверен, как выглядят ваши данные, но в моем примере мое сообщение возвращается через запятую, поэтому я могу разбить строку на массив строк, используя запятую в качестве разделителя, и получить каждое значение из сообщения.
public void Eval_String(string s)
{
string[] eachParam;
eachParam = s.Split(',');
if (eachParam.Length == 5)
{
//do something
Console.WriteLine(eachParam[2]);
}
}
Редактировать: Вот пример того, как обновить ваш графический интерфейс с помощью очереди.
StringBuilder sb = new StringBuilder();
char LF = (char)10;
Queue<string> q = new Queue<string>();
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
foreach (char c in Data)
{
if (c == LF)
{
sb.Append(c);
CurrentLine = sb.ToString();
sb.Clear();
q.Enqueue(currentLine);
}
else
{
sb.Append(c);
}
}
}
private void backgroundWorkerQ_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
if (backgroundWorkerQ.CancellationPending)
break;
if (q.Count > 0)
{
richTextBoxTerminal.AppendText(q.Dequeue());
}
Thread.Sleep(10);
}
}
Если вы никогда не работали с фоновым рабочим, вам просто нужно создать нового фонового рабочегообъект, установите supportsCancellation
в true, затем добавьте событие для его DoWork
.Затем, когда вы запускаете форму, вы можете сообщить ей .RunWorkerAsync()
.
if (!backgroundWorkerQ.IsBusy)
{
backgroundWorkerQ.RunWorkerAsync();
}
См .: https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.7.2 Также обратите внимание, что backgroundworker находится в своем собственном потоке, и вам, скорее всего, потребуется BeginInvokeэто обновить текстовое поле.