c# winform多线程死循环踩坑

 更新时间:2023年12月22日 09:56:47   作者:一瓶酒九块九  
本文主要介绍了c# winform多线程死循环踩坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

问题:

我在一个子窗体中创建了三个线程,分别读取一个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]) 。

到此这篇关于c# winform多线程死循环踩坑的文章就介绍到这了,更多相关c# winform多线程死循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# 内部类与Lambda表达式用法详解

    C# 内部类与Lambda表达式用法详解

    Lambda表达式是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象,是一个匿名函数,即没有函数名的函数;内部类是将一个类定义在另一个给类里面或者方法里面,这样的类就被称为内部类
    2021-10-10
  • C# cefSharep控件的使用详情

    C# cefSharep控件的使用详情

    本文主要介绍了C# cefSharep控件的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • C# WPF ListView控件的实例详解

    C# WPF ListView控件的实例详解

    这篇文章主要介绍了C# WPF ListView控件的实例详解的相关资料,希望通过本能帮助到大家,让大家掌握这部分内容,需要的朋友可以参考下
    2017-10-10
  • WPF实现动画效果(二)之From/To/By动画

    WPF实现动画效果(二)之From/To/By动画

    这篇文章介绍了WPF实现动画效果之From/To/By动画,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 聊聊C#中的Mixin的具体用法

    聊聊C#中的Mixin的具体用法

    本文主要介绍了C#中的Mixin的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • 使用GPS经纬度定位附近地点(某一点范围内查询)

    使用GPS经纬度定位附近地点(某一点范围内查询)

    目前的工作是需要手机查找附近N米以内的商户,致想法是已知一个中心点,一个半径,求圆包含于圆抛物线里所有的点,经纬度是一个点,半径是一个距离,不能直接加减,下面提供C#的解决方法
    2013-12-12
  • C#的winform如何嵌套另一个exe程序

    C#的winform如何嵌套另一个exe程序

    这篇文章主要介绍了C#的winform如何嵌套另一个exe程序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • c#类的使用示例

    c#类的使用示例

    这篇文章主要介绍了c#类的使用示例,还有我学习时的笔记,需要的朋友可以参考下
    2014-04-04
  • C# 如何实现一个基于值相等性比较的字典

    C# 如何实现一个基于值相等性比较的字典

    这篇文章主要介绍了C# 如何实现一个基于值相等性比较的字典,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2021-02-02
  • C#计算矩阵的逆矩阵方法实例分析

    C#计算矩阵的逆矩阵方法实例分析

    这篇文章主要介绍了C#计算矩阵的逆矩阵方法,较为详细的分析了逆矩阵的计算原理与相关的C#实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08

最新评论