如何创建功能性的永不结束的任务/循环?-带串行端口的C#
所以我正在创建一个Windows窗体应用程序,它将通过串行端口持续显示来自Arduino微控制器的更新传感器数据。我对C#还是相当陌生的,更是如此,Arduino。我的问题是,当我试图通过计时器显示更新的传感器数据时,应用程序崩溃 arduino发送如下格式的字符串1;25-其中第一个数字1或0表示运动传感器是否检测到运动。另一个数字是温度如何创建功能性的永不结束的任务/循环?-带串行端口的C#,c#,multithreading,loops,timer,arduino,C#,Multithreading,Loops,Timer,Arduino,所以我正在创建一个Windows窗体应用程序,它将通过串行端口持续显示来自Arduino微控制器的更新传感器数据。我对C#还是相当陌生的,更是如此,Arduino。我的问题是,当我试图通过计时器显示更新的传感器数据时,应用程序崩溃 arduino发送如下格式的字符串1;25-其中第一个数字1或0表示运动传感器是否检测到运动。另一个数字是温度 class ArduinoComClass : SerialPort { public string receivedData; priva
class ArduinoComClass : SerialPort
{
public string receivedData;
private bool dataReady = false;
public ArduinoComClass(string comport, int baudrate)
{
PortName = comport;
BaudRate = baudrate;
DataReceived += new SerialDataReceivedEventHandler(dataReceived);
ReadTimeout = 2000;
Open();
}
~ArduinoComClass()
{
Close();
}
public void ConvertString(out string pirValue, out string tempValue)
{
string[] data = receivedData.Split(';');
string string1 = data[0];
if (string1 == "1")
{
pirValue = "Movement detected!";
}
else
{
pirValue = "No movement detected";
}
string string2 = data[1];
tempValue = string2;
}
public bool DataReady
{
get
{
return dataReady;
}
set
{
dataReady = value;
}
}
public void dataReceived(object sender, SerialDataReceivedEventArgs earg)
{
try
{
receivedData = ReadLine();
dataReady = true;
}
// catch(TimeoutException e)
catch (Exception e)
{
MessageBox.Show(e.Message);
dataReady = false;
}
}
}
现在,这是我要在其中显示数据的表单的代码。这是非常混乱,因为我尝试了很多不同的事情,只是不断地让事情变得更糟。我尝试了任务/线程,但由于receivedData位于另一个线程中,因此出现了一个错误
static private ArduinoComClass ArduinoCom = new ArduinoComClass("COM3", 9600);
private string pirValue;
private string tempValue;
public Main()
{
InitializeComponent();
pirValue = "";
tempValue = "";
tmrAlarm.Start();
}
private void ShowSensorInfo()
{
while (true)
{
if (ArduinoCom.DataReady)
{
ArduinoCom.ConvertString(out pirValue, out tempValue);
txtShowTemp.Text = tempValue;
if (pirValue == "Movement detected!")
{
picPIR.BackColor = Color.Red;
}
else
{
picPIR.BackColor = Color.Lime;
}
//if (SystemInformation.PowerStatus.PowerLineStatus) <- Ignore for now
ArduinoCom.DataReady = false;
}
}
}
private async void tmrAlarm_Tick(object sender, EventArgs e)
{
try
{
Task myTask = Task.Run(() => ShowSensorInfo());
await myTask;
myTask.Wait(2000);
}
catch (Exception error)
{
Console.WriteLine(error.Message);
}
}
静态私有ArduinoComClass ArduinoCom=新的ArduinoComClass(“COM3”,9600);
私有字符串值;
私有字符串值;
公用干管()
{
初始化组件();
pirValue=“”;
tempValue=“”;
tmrAlarm.Start();
}
私有void ShowSensorInfo()
{
while(true)
{
if(ArduinoCom.DataReady)
{
ConvertString(out-pirValue,out-tempValue);
txtShowTemp.Text=临时值;
如果(pirValue==“检测到移动!”)
{
picPIR.BackColor=Color.Red;
}
其他的
{
picPIR.BackColor=颜色.石灰;
}
//if(SystemInformation.PowerStatus.PowerLineStatus)ShowSensorInfo();
等待我的任务;
myTask.Wait(2000);
}
捕获(异常错误)
{
Console.WriteLine(错误消息);
}
}
因此,简言之,我如何能以一种简单有效的方式让我的程序显示这些实时数据而不让应用程序崩溃?线程是答案。你可以从另一个线程更新UI,只需使用Dispatch.Invoke。有关更多详细信息,请参阅我正在尝试理解代码,但是,我很难弄清楚如何将其融入到应用程序中在我的代码中,我很少执行线程。有什么理由通过计时器轮询数据吗?似乎是侦听DataReceived事件并通过Control.Invoke方法(本例中为Form.Invoke方法)更新UI当它触发时就足够了。我尝试使用Timer的唯一原因基本上是因为这是我知道的唯一解决方案。我以前没有听说过Invoke。但是我会检查它,看看是否可以从中获得一些东西。我明白了。使用Timer.Tick事件是更新UI的一种方法,因为它是在UI线程中触发的。另一方面,你可以通过Control.Invoke方法更新UI,即使该方法是从非UI线程中激发的事件调用的。