为 Label.Text 赋值最终会导致 StackOverflowException

Assigning a value to Label.Text eventually results in StackOverflowException

我正在构建一个仪表板样式的 Windowsform,我有各种计时器来更新窗体上的控件,并且一切都很好,除了一个,唯一一个我使用标签控件作为指示器。

我有各种 System.Timers 来更新所有存储在 classes 中的指标数据 运行 每 5 分钟左右,然后设置另一个计时器来更新 GUI 运行秒每秒。出于某种原因,这段代码:

l_LastShipment.Text = GlobalStatic.fulfillmentInd.Caption;

在 GUI 更新中,通常会在几个小时后最终在 WhosebugException 中出错。 fulfillmentInd.Caption 只是 class 中的一个字符串变量,在错误发生时包含正确的数据(通常是“0:01”或类似的东西)。

最初 GUI 计时器是 System.Timer 但担心更新标签的调用是错误的来源,因此将 GUI 计时器切换为 Windows.Forms.Timer 所以它没有require Invoke,还是报错

没有发生递归,我什至监控了更新 GUI 函数到 运行 所花费的时间,它总是小于 1/10 秒,即使发生错误也是如此。

这是修剪后的 GUI 刷新功能:

        private void guiHandleTimer(object sender, EventArgs e)
    {
        //Refresh the Indicators

        //Stopwatch
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();

        //Compact indicator
        if (GlobalStatic.compactInd.Changed())
        {
            pb_Compact.Value = GlobalStatic.compactInd.value;
            pb_Compact.Caption = GlobalStatic.compactInd.Caption;
            pb_CompactTT.SetToolTip(pb_Compact, GlobalStatic.compactInd.tooltip);
            GlobalStatic.compactInd.Reset();
        }


        //
        //Other Indicators removed for readability
        //

        //Fulfillment Indicator
        if (GlobalStatic.fulfillmentInd.Changed())
        {
            if (GlobalStatic.fulfillmentInd.value <= 59)
            {
                //Within an Hour, Light Yellow
                p_fulfillment.BackColor = Color.LightYellow;

            }
            else if (GlobalStatic.fulfillmentInd.value <= 300)
            {
                //Between an hour and 5 hours, Change to Green
                p_fulfillment.BackColor = Color.Green;
            }
            else
            {
                //Over 5 hours old, Grey
                p_fulfillment.BackColor = Color.LightGray;
            }
            l_LastShipment.Text = GlobalStatic.fulfillmentInd.Caption;     <-------This is the line that generates the Whosebug ----->
            ToolTip test = new ToolTip();
            test.SetToolTip(p_fulfillment, GlobalStatic.fulfillmentInd.tooltip);
            test.SetToolTip(l_LastShipment, GlobalStatic.fulfillmentInd.tooltip);
            GlobalStatic.fulfillmentInd.Reset();
        }
        stopwatch.Stop();
        TimeSpan t = stopwatch.Elapsed;
        if(TimeSpan.Compare(largestTime,t)==-1)
        {
            //largestTime is shorter than t, change largestTime
            largestTime = t;
        }
        T_GUI.Text = largestTime.ToString(@"hh\:mm\:ss\:fff");
    }

这是在窗体加载期间调用的计时器设置,代码中唯一提到 GUIHandleTimer 的地方:

            //GUI Refresh Timer
        System.Windows.Forms.Timer guiTimer = new System.Windows.Forms.Timer();
        guiTimer.Interval = 1000;
        guiTimer.Tick += new EventHandler(guiHandleTimer);

我解决了 Whosebug。我花了这么长时间才弄清楚并最终在这里问的原因是 Visual Studio 总是在我最初的问题中突出显示的 Label.Text 行上进行代码破解。不幸的是,那不是导致 Whosebug 的行,而是导致它的下一行。

ToolTip test = new ToolTip();

出于某种原因,我在修复工具提示后没有将 New ToolTip() 移出处理程序,因此我每秒都会将新的工具提示重载到堆栈中。将该行移出函数修复了错误。

奇怪的是,Visual Studio 没有在标记 Whosebug 错误的地方,导致在尝试解决它时遇到很多麻烦。