问题:
我在一个子窗体中创建了三个线程,分别读取一个PLC的50个标签,一共150个,当我把子窗体打开时开始读取,当把子窗体关闭后停止读取,再次打开时又重新开始读取。
第一次打开时速度(ms)是这样的:
第二次就变成了这样:
时间差不多翻了一倍,开关子窗体的次数越多越慢。
循环读取数据的代码如下:
一共三个,这里只放一个,另外两个是差不多的
private async void ReadPlcData1()
{
while (true)
{
try
{
stopwatch1 = Stopwatch.StartNew();
plcData1[0] = await readOmronData.ReadOneOmronData(FrmMain.omronCipNet1, "s_SysStrip1.Status.Homed", "BOOL");
plcData1[1] = await readOmronData.ReadOneOmronData(FrmMain.omronCipNet1, "s_SysStrip1.Status.Homing", "BOOL");
plcData1[2] = await readOmronData.ReadOneOmronData(FrmMain.omronCipNet1, "s_SysStrip1.Status.ErrHome", "BOOL");
plcData1[3] = await readOmronData.ReadOneOmronData(FrmMain.omronCipNet1, "s_SysStrip1.Status.MoveDone", "BOOL");
.......
plcData1[49] = await readOmronData.ReadOneOmronData(FrmMain.omronCipNet1, "s_SysStrip1Move.Cmd.Pos.JogVel", "REAL");
for(int i = 0; i < 50; i++)
{
string labelName = $"label{i+1}";
Control[] labels = Controls.Find(labelName, true);
foreach (var label in labels)//修改label
{
if (label.Name == labelName)
{
Invoke(new Action(() =>
{
label.Text = plcData1[i].ToString();
}));
}
}
}
stopwatch1.Stop();
TimeSpan elapsed = stopwatch1.Elapsed;
Invoke(new Action(() =>
{
RecvCount++;
tb_recvCount.Text = RecvCount.ToString();
tb_timeSpan1.Text = elapsed.TotalMilliseconds.ToString();
}));
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message, "HomeReadData");
}
}
}
创建线程的代码如下
private void StartThreadReadPlcData1()
{
// 启动线程
threadReadPlcData1 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData1));
threadReadPlcData1.IsBackground = true;
threadReadPlcData1.Start();
// 启动线程
threadReadPlcData2 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData2));
threadReadPlcData2.IsBackground = true;
threadReadPlcData2.Start();
// 启动线程
threadReadPlcData3 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData3));
threadReadPlcData3.IsBackground = true;
threadReadPlcData3.Start();
}
答案:
就是死循环,线程没有被释放掉。
每次打开这个窗体会创建3个后台线程,线程中是一个while循环,不断的读取数据,当子窗体关闭时后台线程应该被释放掉,但是实际上这个while循环没有被释放,仍然在运行,也就是说每次打开子窗体,都会创建3个释放不掉的线程占据资源,所以会越来越卡。
解决:
添加循环结束标志,在子窗体关闭的时候结束while循环。
private void FrmMenu_FormClosing(object sender, FormClosingEventArgs e)
{
for (int i = 0; i < stopThreadFlag.Length; i++)
{
stopThreadFlag[i] = true;
}
}
然后读取数据的循坏while(true)改为while (!stopThreadFlag[i]) 。