C#背景工作者-如何为重复性任务触发它
我从一个串行端口接收数据,将每一行放入一个队列,然后对这些行进行解队列,稍微格式化(删除一些前导字符、修剪等),然后在列表框中显示格式化的行 我使用定时器每200毫秒触发一次排队方法。一切正常,但似乎有点慢 我正在考虑使用BackgroundWorker来处理去排队和格式化,但是我被卡住了 我试图在FormLoad中启动backgroundworker,但很快意识到它只能在代码中运行一次。我尝试在backgroundworker代码中添加一个标签并创建一个循环(我知道,不太好),但这让我的CPU使用率很高,甚至无法工作 我还尝试在serial received事件中使用“backgroundWorker1.RunWorkerAsync();”在每次新数据输入时运行它,但这会引发“后台工作人员当前正忙”异常 因此,我需要后台工作人员连续处理队列(出列) 代码:这是我的data received事件,下面是我在backgroundworker中的出列代码。非常感谢您的帮助C#背景工作者-如何为重复性任务触发它,c#,backgroundworker,deque,C#,Backgroundworker,Deque,我从一个串行端口接收数据,将每一行放入一个队列,然后对这些行进行解队列,稍微格式化(删除一些前导字符、修剪等),然后在列表框中显示格式化的行 我使用定时器每200毫秒触发一次排队方法。一切正常,但似乎有点慢 我正在考虑使用BackgroundWorker来处理去排队和格式化,但是我被卡住了 我试图在FormLoad中启动backgroundworker,但很快意识到它只能在代码中运行一次。我尝试在backgroundworker代码中添加一个标签并创建一个循环(我知道,不太好),但这让我的CPU
// Serial Data Received
private void serialPort1_DataReceived(
object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadTo("\u0003");
q.Enqueue(RxString);
}
下一个代码是出列代码:
// Dequeue items, format, then display in listbox
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (q.Count == 0)
{
// do nothing if q is empty
}
else
do
{
output = (q.Dequeue().ToString());
output = output.TrimStart(new char[] { (char)02 });
output = output.TrimEnd(new char[] { (char)03 });
if (output.StartsWith("C"))
{
ClearAll();
}
else if (output.StartsWith("W98"))
{
txtTax.Text = (output.Remove(0, 5));
}
else if (output.StartsWith("W99"))
{
txtTotal.Text = (output.Remove(0, 24));
}
else
{
listOrderItems.Items.Add(output.Remove(0, 5));
listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
}
} while (q.Count > 0);
}
我看不出在其他线程中解析字符串有什么意义。这不是一个很长的运行过程,而且由于您在后台线程中运行,您似乎忘记了调用windows线程。下面是我的解决方案
using System.IO.Ports;
static void ParseData(ref string data)
{
data = data.TrimStart(new char[] { (char)02 });
data = data.TrimEnd(new char[] { (char)03 });
}
private void UpdateControlsWithData(string data)
{
Action action;
if(data.StartsWith("C")
{
action = () => ClearAll();
}
else if(data.StartsWith("W98"))
{
action = () => { txtTax.Text = data.Remove(0, 5); };
}
else if(data.StartsWith("W99"))
{
action = () => { txtTotal.Text = data.Remove(0, 24); };
}
else
{
action = () => {
listOrderItems.Items.Add(data.Remove(0, 5));
listOrderItems.SelectedIndex = listOrderItems.Items.Count - 1;
};
}
if(this.InvokeRequired()) this.Invoke(action);
else action();
}
private void HandleDataReceived()
{
string data = serialPort1.ReadTo("\u0003");
ParseData(ref data);
UpdateControlsWithData(data);
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.HandleDataReceived();
}
线程太多。你已经有一只手放在银盘上了:DataReceived事件在线程池线程上运行。在那里执行消息处理。然后使用Control.BeginInvoke更新任何UI。@Hans:答案在下面(即使是简短的答案)它并没有回答这个问题,用户对此会感到不安。Hans,你的评论是否意味着DataReceived事件已经在类似BackgroundWorker的程序中运行?如果是,你的“太多线程”评论是否意味着创建额外线程不好?如何确定有多少线程太多?当你说。“在那里处理消息吗“您的意思是将所有格式代码移到DR事件中吗??如果是这样,这就引出了另一个问题:我甚至需要BgW吗?我需要这是回应。这个程序不会做任何太复杂的事情,但我需要它快速稳定。我把我的格式化代码放入DataRec。事件处理程序。它一点也不好用。作为礼貌性的跟进,我确实不需要启动任何新的线程。我创建了一个新队列,以逐行保存串行数据,作为主要传入数据处理程序。然后,我使用一个计时器将队列中的所有项目出列,并在我的列表框和标签中操作、格式化和显示它们。感谢那些插话的人!