【问题标题】:Multithreading or something different多线程或不同的东西
【发布时间】:2013-07-04 16:08:06
【问题描述】:

这是我第一次遇到这样的问题。这不是我的职业,只是我的爱好,我没有以前的参考资料。 在我的程序中,我一一添加了几个功能来控制机器。添加最后一个功能(温度测量)后,我开始在其他功能上遇到问题(其中大约 8 个一起运行。我遇到的问题在与此无关的图表(电机的 RPM)上功能但受它的影响。您可以看到这两个图表在运行和不运行温度测量时的区别。两个图表中电机的实际速度相同,但在第二个图表中,由于应用程序变慢,我在运行中松散了碎片下来。

没有温度功能。 带温度功能

特别是这个功能干扰了上述控制,我认为是因为应用程序的工作量变得越来越重,或者因为我需要采样,所以有一些时间等待获得它们:

private void AddT(decimal valueTemp)
    {
        sumTemp += valueTemp;
        countTemp += 1;
        if (countTemp >= 20) //take 20 samples and make average
        {
            OnAvarerageChangedTemp(sumTemp / countTemp);
            sumTemp = 0;
            countTemp = 0;
        }
    }
    private void OnAvarerageChangedTemp(decimal avTemp)
    {
        float val3 = (float)avTemp;
        decimal alarm = avTemp;


            textBox2.Text = avTemp.ToString("F");


           if (alarm > 230)
           {

               System.Media.SoundPlayer player = new System.Media.SoundPlayer();
               player.Stream = Properties.Resources.alarma;
               player.Play();
               timer4.Start();
           }

           else
           {
               timer4.Stop();
               panel2.BackColor = SystemColors.Control;
           }
    }

我想知道在不同的线程上运行这个函数是否可以解决问题,我该怎么做?或者如果有其他方法可以解决问题。示例代码将不胜感激。

更新,添加方法调用。

这就是我调用 AddT 方法的方式

if (b != "")
            {

                decimal convTemp; //corrente resistenza
                decimal.TryParse(b, out convTemp);
                AddT(convTemp);}

This 是我从串行接收数据并将其传递给去除不常见字符并将值返回给不同变量的类的方式。 This 是去除不常见的字符并返回值的类。 this 是我管理串行传入数据的方式。看到我的编码后请不要嘲笑我。我做不同的工作,我正在自学。

【问题讨论】:

  • 你为什么使用十进制?如何“控制机器”? AddT 怎么称呼?为什么你认为它太慢了?
  • 首先找出你真正的问题。如果 CPU 负载太高,您应该获得更少的值,但不会出现错误(较低)的值。您的症状不支持您的假设。
  • 很难从您发布的内容中看出,但您确实在 UI 线程中做得太多了。例如,我有线程来收集数据。用于监视警报数据的线程。然后根据我检测到的感兴趣的内容,在需要时更新 UI(或其部分)的线程。
  • 好吧,看起来还不错(没什么明显的)。您是否尝试过省略其他功能并查看它是否再次开始工作?还要检查 CPU 负载(如果它真的太高)。您多久从 Arduino 获取数据?
  • 我没有答案,但我确实发现了一些可疑的东西。在读取 rpm 值的代码(pastebin 链接)中,您将用空字符串替换出现的“0”。我不确定您是否正在考虑那里的前导零,但这不会将“30”的读数更改为“3”吗?等等……

标签: c# multithreading backgroundworker


【解决方案1】:

很难判断是否有任何问题以及可能是什么 - 这看起来像是一个微妙的问题。

但是,如果您重构代码,可能会更容易处理这些事情。您展示的代码中有很多东西使得推理发生的事情变得比必要更难。

  • 您正在使用floatdecimal - float 不是那么准确,而是小而快; decimal (尝试)要精确,但尤其是可预测的,因为它以人类可能以 10 为基数的方式舍入错误 - 但它非常慢,通常用于需要精确再现性的计算(例如金融资料)。您可能应该在任何地方使用double
  • Stripper 类中有无用的 else {} 代码。
  • 您的 Stripper 是一个不可静态的类,而它应该只是一个带有静态方法的静态类 - Stripper 是无状态的。
  • 您捕获异常只是为了重新抛出它们。
  • 您正在使用TryParse,而不是检查是否成功。通常,如果您 (a) 期望解析有时会失败,您只会使用 TryParse,and (b) 可以处理该解析失败。如果您没有预料到失败或无法处理它,那么您最好尽快了解崩溃,而不是稍微不正确的值。
  • 在剥离器中,您复制了 _currentMotcurrentMotparam4 等变量,但它们是相同的 - 仅使用参数,并为其指定一个逻辑名称。
  • 您正在使用out 参数。定义一个简单的 struct 并返回它几乎总是一个更好的主意 - 这也允许您确保您不能轻易混淆变量名称,并且封装和重用功能更容易,因为您不需要复制一个长调用和参数定义。
  • 你的字符串解析逻辑太脆弱了。您可能应该完全避免Replace,而是在没有您检查过的字符的情况下明确创建Substring,并且您有一些奇怪的名称,例如test1test2,它们引用了lastChar,这不是最后一个字符 - 这可能没问题,但更好的名称也可以帮助您保持头脑清醒。
  • 您的代码 cmets (decimal convTemp; //corrente resistenza) 不正确。我通常会避免所有纯粹的技术代码 cmets;最好使用描述性变量名称,这是另一种形式的自记录代码,但编译器至少可以检查您是否始终如一地使用它们。
  • 而不是返回 4 个可能为空的值,您的 Stripper 可能应该接受一个参数“sink”对象,它可以在该对象上直接调用 AddT AddDAddA

我认为以上任何方法都不能解决您的问题,但我相信它们有助于使您的代码更简洁一些,并且(从长远来看)更容易找到问题。

【讨论】:

  • 感谢您的建设性意见。真的很感激并激励我修改代码以清理它。我会在整理好你指出我的问题后寻找问题。正如你所说,可能会更容易找到问题所在,我同意这个观点。不幸的是,我并没有计划好最终添加到这个应用程序中的所有功能,因此我会不断添加更多功能。
  • 祝你重构顺利!
  • 看起来重构效果不错。我越简化代码并使其密封,反应时间越长,最终结果就越稳定。
  • 听起来你确实有性能问题。
【解决方案2】:

您的问题在于解析您拥有的值

decimal.TryParse(a, out convRes);
AddA(convRes);

并且不检查失败的值,您只接受返回 true 的值

if(decimal.TryParse(a, out convRes))
{
   AddA(convRes);
}

您可能会遇到更多错误,但每次 TryParse 失败时,此错误都会让您处理 0 个值。

【讨论】:

  • 谢谢。我试过了,但没有任何改进。我实际上正在使用空调制解调器而不是 Arduino 进行一些测试,以确保问题出在应用程序方面。我会分享结果。
  • 尝试做一个小测试,只用一两个函数计算无效 TryParse 的数量,然后重新激活所有函数,这可能是您可以通过串行端口发送的数据量的限制。
猜你喜欢
  • 1970-01-01
  • 2019-03-01
  • 2011-05-10
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多