У меня есть большие проблемы с последовательными запросами.Последовательная связь получает неправильный ответ, когда что-то работает в фоновом режиме (например, просмотр жесткого диска)
Описание от того, что я хочу:
установить последовательное соединение, отправить последовательные запросы до 6 температуры датчики один за другим (это делается каждый 0,5 секунды в цикле)
вопрос и ответ-адресат хранятся в массиве List
каждый запрос запускается в отдельном потоке, поэтому gui не вызывает ошибку , пока программа ждет для датчика-метиз ответить
Моей проблема:
Подключения и запрос работают нормально, но если я просматриваю данные на локальном жесткий диске ответ от датчика-блока разрушаются (отрицательный алгебраический знак или значение от другого датчика или просто неправильное значение). Как это происходит или как я могу это решить?
Где я думаю, что проблема может быть:
- В частном ничтожной ReceiveThread() класса SerialCommunication
Вот мой код:
Класс CommunicationArray:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hardwarecommunication
{
public class CommunicationArray
{
public string request { get; set; }
public object myObject { get; set; }
public string objectType { get; set; }
}
}
SerialCommunication Класс
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace Hardwarecommunication
{
class SerialCommunication
{
Thread t2;
Thread t;
private SerialPort serialPort = new SerialPort("COM2", 115200, Parity.Even, 8, StopBits.One);
string serialAnswer = "";
private volatile bool _shouldStop;
private int counter;
List<CommunicationArray> ar = new List<CommunicationArray>();
object[] o = new object[3];
public void addListener(string request, object myObject, string objectType)
{
CommunicationArray sa = new CommunicationArray();
sa.request = request;
sa.myObject = myObject;
sa.objectType = objectType;
ar.Add(sa);
}
public void startListen()
{
t2 = new Thread(() => writeSerialPortThread());
t2.Start();
}
public void startSerialPort2()
{
try
{
serialPort.Open();
//MessageBox.Show("Connection opend!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
public void stopSerialPort2()
{
try
{
if (serialPort.IsOpen == true)
// Connection closed
serialPort.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void writeSerialPortThread()
{
string request = "";
for (int i = 0; i < ar.Count(); i++)
{
request = ar[i].request;
//request = ((object[])ar[0])[0].ToString();
//if (!t.IsAlive)
//{
try
{
t = new Thread(ReceiveThread);
_shouldStop = false;
//MessageBox.Show("start thread");
t.Start();
serialPort.Write(request);
Thread.Sleep(50);
_shouldStop = true;
t.Join();
}
catch
{
}
Label tmpLabelObject = (Label)ar[i].myObject;
serialAnswer = serialAnswer.Replace("=", "");
if (tmpLabelObject.InvokeRequired)
{
MethodInvoker UpdateLabel = delegate
{
tmpLabelObject.Text = serialAnswer;
};
try
{
tmpLabelObject.Invoke(UpdateLabel);
}
catch
{
}
}
}
}
private void ReceiveThread()
{
//MessageBox.Show("in thread");
while (!_shouldStop)
{
serialAnswer = "";
try
{
//MessageBox.Show("in thread");
serialAnswer = serialPort.ReadTo("\r");
if (serialAnswer != "")
{
}
return;
}
catch (TimeoutException) { }
}
}
}
}
класса Form1 // установить соединение и начать просить ДАТЧИК
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Hardwarecommunication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private SerialCommunication serialCommunication1 = new SerialCommunication();
private void Form1_Load(object sender, EventArgs e)
{
//start up serial connection
serialCommunication1.startSerialPort2();
}
private void buttonStart_Click(object sender, EventArgs e)
{
timerRecord.Enabled = true;
if (this.buttonStart.Text == "Start")
this.buttonStart.Text = "Stop";
else
this.buttonStart.Text = "Start";
}
private void timerRecord_Tick(object sender, EventArgs e)
{
if (this.buttonStart.Text == "Stop")
{
this.serialCommunication1.startListen();
}
}
private void buttonFillRequestArray_Click(object sender, EventArgs e)
{
this.serialCommunication1.addListener("$0BR00\r" + "\r", this.labelResult0, "label0"); //request to the hardware
this.serialCommunication1.addListener("$0BR01\r" + "\r", this.labelResult1, "label1");
this.serialCommunication1.addListener("$01R00\r" + "\r", this.labelResult2, "label2");
this.serialCommunication1.addListener("$01R01\r" + "\r", this.labelResult3, "label3");
this.serialCommunication1.addListener("$01R02\r" + "\r", this.labelResult4, "label4");
}
}
}
Я woud быть рад любой попытаться исправить проблема. Я также могу загрузить решение в формате .zip, но вы не можете его полностью протестировать, потому что у вас нет аппаратного обеспечения датчика.
Ваша программа, вероятно, очень чувствительны к времени. Это то, что вы получаете, когда начинаете добавлять Thread.Sleep() в свой код, чтобы заставить его работать. Нет никакой гарантии, что метод ReceiveThread() даже вызовет serialPort.ReadTo(), он немедленно выйдет, когда он запустится с опозданием. Тайм-аут глотания Исключение без какой-либо диагностики также крайне неразумно. Начните с удаления этого потока, он не служит никакой полезной цели, кроме как сбой вашего кода. –
Вам нужно использовать детерминированный подход к потоковому использованию. У вас нет шансов на успех в вашем текущем подходе. Сроки не могут использоваться для управления программой. – usr
Привет, мне приятно посмотреть, как это выглядит как маленький пример. Thx – kimliv