为什么我的 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,我们可能会给出一个更好的例子。
基本上,我做了一个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,我们可能会给出一个更好的例子。