为什么我的 System.Timers.Timer 通过不同的线程获取 stackoverflow?

Why am I getting stackoverflow on my System.Timers.Timer through a different thread?

基本上,我做了一个System.Timers.Timer定时器,我用了一个方法来打开一个新线程和运行定时器。每当有什么变化时,比如当我不在游戏中时,它就会改变标签,然后两秒钟后它就会崩溃。我尝试使用 Dispatcher.Invoke() 来防止出现“不同线程”错误,它成功地更改了标签然后崩溃,我还使用了 Dispatcher.BeginInvoke(),这让我得到了 AccessException 或其他东西。我正在尝试找到一种方法使其不会崩溃,并在更改不同标签时使其 运行 顺利。

System.Timers.Timer tm = new System.Timers.Timer();
System.Timers.Timer tma = new System.Timers.Timer();
public ElapsedEventHandler Injection()
        {
            if (inject == true)
            {
                Dispatcher.Invoke(new Action(delegate
                {
                    tm.Start();
                    tma.Stop();
                    StatusLabel.Content = "Injecting..".ToString();
                }));
            }
            else if (api.currentlyinjecting == true)
            {
                Dispatcher.Invoke(() =>
                {
                    if (StatusLabel.Content.ToString() == "Injecting..")
                    {

                    }
                    else
                    {
                        StatusLabel.Content = "Injecting..";
                    }
                });
                tm.Start();
                tma.Stop();
            }
            else
            {
                if (api.AlreadyInjected() == false)
                {
                    Dispatcher.Invoke(() =>
                    {
                        if (StatusLabel.Content.ToString() == "Not Injected")
                        {

                        }
                        else
                        {
                            StatusLabel.Content = "Not Injected";
                        }
                    });
                }
                else
                {
                    Dispatcher.Invoke(() =>
                    {
                        if (StatusLabel.Content.ToString() == "Not Injected")
                        {

                        }
                        else
                        {
                            StatusLabel.Content = "Not Injected";
                        }
                    });
                }
            }
            return Injection();
        }
        public ElapsedEventHandler Injection2()
        {
            if (api.AlreadyInjected())
            {
                if (StatusLabel.Content.ToString() == "Injected")
                {
                    if (api.AlreadyInjected() == false)
                    {
                        tma.Start();
                        tm.Stop();
                    }
                }
                else
                {
                    Dispatcher.Invoke(() =>
                    {
                        StatusLabel.Content = "Injected";
                    });
                }
            }
            return Injection2();
        }

您在 Injection 方法的末尾调用 return Injection();,这将导致永无止境的递归。

In software, a stack overflow occurs if the call stack pointer exceeds the stack bound. The call stack may consist of a limited amount of address space, often determined at the start of the program. source

简单地说:当调用一个方法时,当前variables/arguments被压入栈中(线程绑定的一些内存),并在退出该方法时被清理。如果您一遍又一遍地调用方法内的方法,使用的内存将 stack-up,直到您超过它的大小。您的程序将因计算器溢出而崩溃。 (这也不例外,你可以 try/catch)

Injection2也一样。

Injection 方法应该由计时器调用,而不是由您的方法调用。


您应该为 WPF 使用 DispatcherTimer,这将使代码更简洁,因为您不需要调用。

如果您多讲一点 API,我们可能会给出一个更好的例子。