所以我有这个 C# 应用程序,它从 Arduino 获取值(6 个变量)。最初我使用了一个计时器,每 100 毫秒调用一些读取函数,但它挂起我的 UI 并且响应有点重。我想使用一个后台 worker 来连续读取这些变量。我将这些读取调用放在 DoWork 方法中,并将值放入 C# 的变量中,并将它们分配到标签或其他内容中。但这不起作用。 (抱歉我的英语)
namespace testtemp
{
public partial class tempreaderform : Form
{
public tempreaderform()
{
InitializeComponent();
}
communicator comport = new communicator();
Boolean portConnection = false;
String red_light1;
private void button1_Click(object sender, EventArgs e)
{
if (comport.connect(57600, "I'M ARDUINO", 4, 8, 16))
{
label1.Text = "Connection Successful - Connected to "+comport.port;
portConnection = true;
backgroundWorker1.RunWorkerAsync(); // I am not sure if here I should start the backgroundworker.
}
else
{
label1.Text = "Not connected . . . ";
portConnection = false;
}
}
private void groupBox1_Paint(object sender, PaintEventArgs e)
{
Graphics ellipse1 = groupBox1.CreateGraphics();
Brush red_on = new SolidBrush(Color.Red);
Brush red_off = new SolidBrush(Color.DarkRed);
label2.Text = "Red : " + red_light1; //Here is a label which I want to show "1" if "red_light1" is "1" and "0" if "red_light1" is "0"
if (red_light1 == "1") ellipse1.FillEllipse(red_on, 250, 133, 24, 24);
else ellipse1.FillEllipse(red_off, 250, 133, 24, 24); // Here is what I really want to do (the label.Text part was only to see the value) I want to color a ellipse depending on "red_light1" value.
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
red_light1 = comport.message(4, 8, 32);
}
}
}
}
}
注意:我在 DoWork 方法中尝试了这个“label1.Text = red_light1”,但它说我无法为另一个线程中创建的变量赋值,就像这样。
最佳答案
“问题”是后台工作人员生活在另一个线程中,而您试图在 UI 线程中使用。并且消息不会在那里传达。
共有三个选项:
要使用
RunWorkerCompleted
事件:您必须使用计时器每 X 毫秒运行一次后台工作程序。private void timer1_Tick(object sender, EventArgs e) { this.backgroundworker.RunWorkerAsync(); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) e.Result = comport.message(4, 8, 32); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { label2.Text = e.Result.ToString(); }
使用
BeginInvoke
设置文本private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while (true) { this.BeginInvoke((Action)(() => { label2.Text = comport.message(4, 8, 32); }); // add some delay here as well... } }
使用
Task
代替backgroundworker并在计时器中调用它。private void timer1_Tick(object sender, EventArgs e) { Task.Run(() => { this.BeginInvoke((Action)(() => { label2.Text = comport.message(4, 8, 32); }); }); }
关于C# - 后台工作人员通过串行从 Arduino 连续获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29819552/