C#计时器功能和行为

时间:2018-12-09 22:17:45

标签: c# timer

因此,我正在使用Timer调用函数,但是我也希望自己也可以调用此函数。我想到的方法是让Timer函数调用实际函数:

public System.Timers.Timer atimer = new System.Timers.Timer();


private void Timer()
        {
            atimer.Elapsed += new System.Timers.ElapsedEventHandler(FunctionCalledByTimer);
            atimer.Interval = 10000;
            atimer.Enabled = true;
        }      

 private void FunctionCalledByTimer(object source, System.Timers.ElapsedEventArgs e)
        {
            CheckOrder();
        }

然后,如果我想在我使用的计时器之外调用该函数:

public void NextPhaseByPlayerInitialized()
        {                              
                atimer.Enabled = false;
                atimer.Enabled = true;
                CheckOrder();                
        }

现在我遇到的问题是CheckOrder具有某些变量,可以通过增加它们来更改它们。如果我使用计时器,则它的工作原理很好,它每次迭代仅增加一个。但是,奇怪的是,如果我在计时器ergo之外手动调用该函数(也在此过程中重置计时器),则到目前为止从计时器端开始发生的所有增量都再次设置为0。

就好像计时器调用的所有内容与计时器外部的所有内容都是分开的一样,第二秒我停止计时器时,变量将返回其原始状态。我的问题是,如果这样的话,首先是这种预期行为吗?其次,有没有解决的办法?

提前获得帮助

完整代码:

using System;
using System.Threading;

class Programm
{
    static void Main(string[] args)
    {

        Caller.Init();
        Object.counters[0].Timer();

    }
}

class Caller
{
    public static void Init()
    {
        for (int i = 0; i < Object.counters.Length; i++)
        {
            Object.counters[i] = new Object.Counter
            {
                currentCount = 0,
                atimer = new System.Timers.Timer()
            };
        }
    }
}

class Input
{
    public void PressButton()
    {
        Object.counters[0].NextPhaseByPlayerInitialized();
    }
}

class Object {

    public static Counter[] counters = new Counter[2];

    public struct Counter
    {
        public int currentCount;
        public System.Timers.Timer atimer;

        public void Timer()
        {
            atimer.Elapsed += new System.Timers.ElapsedEventHandler(FunctionCalledByTimer);
            atimer.Interval = 10000;
            atimer.Enabled = true;
        }

        private void FunctionCalledByTimer(object source, System.Timers.ElapsedEventArgs e)
        {
            CheckOrder();
        }

        public void NextPhaseByPlayerInitialized()
        {
            atimer.Enabled = false;
            atimer.Enabled = true;
            CheckOrder();
        }
        private void CheckOrder()
        {
            Console.WriteLine("currentCount: {0}", currentCount);
            currentCount++;
        }
    }    
}

1 个答案:

答案 0 :(得分:3)

简短答案:

  1. 请不要在C#中使用结构。您唯一可以考虑使用struct的情况是,如果struct很小且不可变(所有标记为readonly且永不更改的字段)。

  2. 请勿使用static对象实例。他们是邪恶的。

  3. 请勿使用public static对象实例。他们真的非常邪恶。

长答案:

struct是C#中的value type,表示它按值传递。这意味着,每当您将struct变量传递给函数时,它将获取此结构的副本,并在函数主体内部的副本上进行操作。返回后,所有更改都消失了。

在这种情况下,发生的情况有些不同,但仍然同样险恶:将结构中的方法附加到timer事件的行实际上创建了{{1}的副本 }和boxes it(分配一个托管堆对象,其中包含您的struct的副本)。

这意味着您所看到的字段的任何更改实际上都不会发生在数组内部的结构上,只有在调用struct时才会发生,这会在实际的Object.counters[0].NextPhaseByPlayerInitialized()上调用该方法。 / p>

您可以重写Object.counters[0]方法以查看计时器实际上是否获得了自己的副本:

CheckOrder

因此,摆脱这些结构。另外,如果您正在编写游戏,那么让计时器在其他线程上触发可能不是一个好主意。