c# winform多線程死循環(huán)踩坑
問(wèn)題:
我在一個(gè)子窗體中創(chuàng)建了三個(gè)線程,分別讀取一個(gè)PLC的50個(gè)標(biāo)簽,一共150個(gè),當(dāng)我把子窗體打開時(shí)開始讀取,當(dāng)把子窗體關(guān)閉后停止讀取,再次打開時(shí)又重新開始讀取。
第一次打開時(shí)速度(ms)是這樣的:
第二次就變成了這樣:
時(shí)間差不多翻了一倍,開關(guān)子窗體的次數(shù)越多越慢。
循環(huán)讀取數(shù)據(jù)的代碼如下:
一共三個(gè),這里只放一個(gè),另外兩個(gè)是差不多的
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() { // 啟動(dòng)線程 threadReadPlcData1 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData1)); threadReadPlcData1.IsBackground = true; threadReadPlcData1.Start(); // 啟動(dòng)線程 threadReadPlcData2 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData2)); threadReadPlcData2.IsBackground = true; threadReadPlcData2.Start(); // 啟動(dòng)線程 threadReadPlcData3 = new System.Threading.Thread(new System.Threading.ThreadStart(ReadPlcData3)); threadReadPlcData3.IsBackground = true; threadReadPlcData3.Start(); }
答案:
就是死循環(huán),線程沒(méi)有被釋放掉。
每次打開這個(gè)窗體會(huì)創(chuàng)建3個(gè)后臺(tái)線程,線程中是一個(gè)while循環(huán),不斷的讀取數(shù)據(jù),當(dāng)子窗體關(guān)閉時(shí)后臺(tái)線程應(yīng)該被釋放掉,但是實(shí)際上這個(gè)while循環(huán)沒(méi)有被釋放,仍然在運(yùn)行,也就是說(shuō)每次打開子窗體,都會(huì)創(chuàng)建3個(gè)釋放不掉的線程占據(jù)資源,所以會(huì)越來(lái)越卡。
解決:
添加循環(huán)結(jié)束標(biāo)志,在子窗體關(guān)閉的時(shí)候結(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WPF實(shí)現(xiàn)動(dòng)畫效果(二)之From/To/By動(dòng)畫
這篇文章介紹了WPF實(shí)現(xiàn)動(dòng)畫效果之From/To/By動(dòng)畫,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06使用GPS經(jīng)緯度定位附近地點(diǎn)(某一點(diǎn)范圍內(nèi)查詢)
目前的工作是需要手機(jī)查找附近N米以內(nèi)的商戶,致想法是已知一個(gè)中心點(diǎn),一個(gè)半徑,求圓包含于圓拋物線里所有的點(diǎn),經(jīng)緯度是一個(gè)點(diǎn),半徑是一個(gè)距離,不能直接加減,下面提供C#的解決方法2013-12-12C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典
這篇文章主要介紹了C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02