繁体   English   中英

奇怪的if语句行为,零值为double

[英]Strange if-statement behavior with zero value double

是否有人愿意向我解释如何将this.oBalance.QouteBalance的值评估为真实,因为它显然不是零? 请看下面的图片。

在比较C#中的双打时,我是否遗漏了一些基本的东西?

在此输入图像描述

public double QouteBalance { get; set; }

UpdateBalance_PositionOpenned()不是在循环中调用,而是作为更复杂的事件驱动过程的一部分调用,该过程在计时器的滴答上运行(毫秒级)

编辑:请原谅代码,如果它很乱,但我无法编辑它,因为这是一个运行时错误经过相当长的运行时间所以害怕无法重新创建它。 异常消息不正确,只是我自己的提醒。 异常后的代码是我在开始此特定运行之前忘记注释掉的代码。

编辑2:我正在发布模式下构建和运行。

编辑3:原谅我的无知,但似乎我实际上是在多线程环境中运行,因为这个代码被调用作为更复杂的对象方法的一部分,该方法在计时器的ticks(事件)上执行。 是否有可能要求计时器等到它的事件处理程序中的所有代码都完成才能再次打勾?

编辑4:由于这已被确定为多线程问题; 我将尝试提供更广泛的背景,以达到优化的解决方案。

我有一个Timer对象,它在每个tick上执行以下操作:

  1. 运行后台工作程序以从文件中读取数据
  2. 当后台工作程序完成从文件中读取数据时,引发一个事件
  3. 在事件处理程序中,运行调用下面方法(在图像中)和其他多个例程(包括GUI更新)的对象代码。

我想通过使用计时器Tick事件来读取来自文件可以避免这个问题,但是更改它会破坏我的代码的其他部分。

您正在从多个线程访问共享变量。 这可能是一个竞争条件,其中一个线程抛出了错误,但是当调试器捕获并附加时,变量的值已经改变。

您需要查看实现同步逻辑,例如锁定共享变量等。

编辑 :要回答您的修改:

你不能真正告诉计时器不要打勾(你可以,但是你开始和停止,甚至在调用停止后你可能仍会收到更多的事件,具体取决于他们被派遣的速度)。 也就是说,您可以查看Interlocked命名空间并使用它来设置和清除IsBusy标志。 如果您的tick方法触发并且看到您已经在工作,那么它只是坐在那一轮并等待未来的滴答来处理工作。 我不会说这是一个很好的范例,但它是一个选择。

我使用Interlocked类而不仅仅使用共享变量来指定的原因归结为您可以同时从多个线程进行访问。 如果你没有使用Interlocked,你可以得到两个滴答,既检查值又得到一个答案,他们可以在他们翻转旗帜以防止其他人离开之前继续。 你遇到了同样的问题。

更常见的同步访问共享数据成员的方法是锁定,但是你很快就会遇到问题,因为tick事件发生得太快,他们会开始备份你。

编辑2 :要回答有关在多个线程上将数据与共享变量同步的方法的问题,这实际上取决于您具体做什么。 我们有一个非常小的窗口可以显示您的应用程序正在执行的操作,因此我将从所有注释和答案中将它拼凑在一起,希望它能够为您的设计选择提供信息。

接下来是伪代码。 这是基于您提出的一个问题,这个问题表明您不需要在每个刻度线上进行操作。 滴答本身并不重要,它只需要继续进入。基于这个前提,我们可以使用标记系统来检查您是否正忙。

...
Timer.Start(Handle_Tick)
...

public void Handle_Tick(...)
{
    //Check to see if we're already busy. We don't need to "pump" the work if
    //we're already processing.
    if (IsBusy)
        return;

    try
    {
        IsBusy = true;

        //Perform your work
    }
    finally
    {
        IsBusy = false;
    }
}

在这种情况下,IsBusy可能是一个易变的bool,它可以使用Interlocked命名空间方法访问,它可以是一个锁定等。你选择的是由你自己决定的。

如果这个前提是不正确的,并且你确实必须对计时器的每个滴答做一些工作,这对你不起作用。 当你忙的时候,你正在扔掉进来的虱子。 如果你想保留每一个滴答声,你需要实现一个同步队列。如果你的频率很高,你必须要小心,因为你最终会溢出。

这不是一个真正的答案,但是:

UpdateBalance_PositionOpenned()不是在循环中调用,而是作为更复杂的事件驱动过程的一部分调用,该过程在计时器的滴答上运行(毫秒级)

看到:

多线程? - abatishchev 30分钟前

毫秒级的紧定时驱动事件循环可能具有线程的所有问题,并且几乎完全不可能使用逐步调试器进行故障排除。 东西发生的速度比你可以击中'F10'的速度快。 更不用说,您在每个事件周期中从不同的线程访问变量,但是看不到同步。

不是一个完整的答案,但是评论过多
这就是我在防守方面的编码方式
本地范围导致意外情况减少
它使代码更容易调试和测试

public void updateBalance(double amount, double fee, out double balance)
{
    try
    {
        balance = amount * (1.0 + fee);
        if (balance < 0.0) balance = 0.0;
    }
    catch (Exception Ex)
    {
        System.Diagnostics.Debug.WriteLine(Ex.Message);
        throw Ex;
    }
}

值类型被复制,因此即使在方法执行方法中的金额值时更改了金额的输入变量也不会。

现在没有锁的外部平衡是一个不同的故事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM