c# winform多線程死循環(huán)踩坑
問題:
我在一個子窗體中創(chuàng)建了三個線程,分別讀取一個PLC的50個標(biāo)簽,一共150個,當(dāng)我把子窗體打開時開始讀取,當(dāng)把子窗體關(guān)閉后停止讀取,再次打開時又重新開始讀取。
第一次打開時速度(ms)是這樣的:

第二次就變成了這樣:

時間差不多翻了一倍,開關(guān)子窗體的次數(shù)越多越慢。
循環(huán)讀取數(shù)據(jù)的代碼如下:
一共三個,這里只放一個,另外兩個是差不多的
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");
}
}
}
創(chuàng)建線程的代碼如下
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();
}
答案:
就是死循環(huán),線程沒有被釋放掉。
每次打開這個窗體會創(chuàng)建3個后臺線程,線程中是一個while循環(huán),不斷的讀取數(shù)據(jù),當(dāng)子窗體關(guān)閉時后臺線程應(yīng)該被釋放掉,但是實際上這個while循環(huán)沒有被釋放,仍然在運行,也就是說每次打開子窗體,都會創(chuàng)建3個釋放不掉的線程占據(jù)資源,所以會越來越卡。
解決:
添加循環(huán)結(jié)束標(biāo)志,在子窗體關(guān)閉的時候結(jié)束while循環(huán)。
private void FrmMenu_FormClosing(object sender, FormClosingEventArgs e)
{
for (int i = 0; i < stopThreadFlag.Length; i++)
{
stopThreadFlag[i] = true;
}
}
然后讀取數(shù)據(jù)的循壞while(true)改為while (!stopThreadFlag[i]) 。
到此這篇關(guān)于c# winform多線程死循環(huán)踩坑的文章就介紹到這了,更多相關(guān)c# winform多線程死循環(huán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用LibUsbDotNet實現(xiàn)USB設(shè)備檢測
C#?LibUsbDotNet是一個.NET平臺上的庫,用于訪問USB設(shè)備,它封裝了Linux下的libusb庫,LibUsbDotNet提供了一個簡單的API,開發(fā)者可以利用這個庫在C#中操作USB設(shè)備,本文介紹了C#使用LibUsbDotNet實現(xiàn)USB設(shè)備檢測,需要的朋友可以參考下2024-07-07
C#面向?qū)ο缶幊讨幸蕾嚪崔D(zhuǎn)原則的示例詳解
在面向?qū)ο缶幊讨校琒OLID?是五個設(shè)計原則的首字母縮寫,旨在使軟件設(shè)計更易于理解、靈活和可維護。本文將通過實例詳細(xì)講講C#面向?qū)ο缶幊讨幸蕾嚪崔D(zhuǎn)原則,需要的可以參考一下2022-07-07
C#使用CallContext緩存線程數(shù)據(jù)
這篇文章介紹了C#使用CallContext緩存線程數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
c#使用S22.Imap收劍靈激活碼郵件代碼示例(imap收郵件)
一個IMAP收發(fā)郵件的類庫S22.IMAP,方便易用,下面來個例子可以收劍靈激活碼郵件2013-12-12

