多个动态计时器

时间:2012-07-05 02:02:44

标签: c# timer

我正在开展一个项目,我需要让用户创建一个(或多个)计时器来触发事件。 用户应该定义变量,例如计时器是否应该处于活动状态以及计时器将触发的频率以及计时器激烈时将发生的其他一些变量。

所有这些变量都存储在字典(Disctionary)中,其中对象包含用户设置的所有变量,字符串是用户为此计时器选择的名称。

然后我希望我的程序遍历这个字典并搜索所有变量t_Active设置为true的对象(我已经实现了)。 我需要帮助解决的问题是: 当它检测到变量时,如果它设置为true,我需要程序查看是否已经为此创建了一个计时器。 如果不是,则应创建一个并为计时器设置相关参数。 两个变量t_num和t_period应该决定定时器的间隔。 t_num是一个int,t_period是一个字符串,它将被设置为分钟,小时或天。

将t_num与60000(分钟),3600000(小时)或86400000组合应该给出corrct间隔。

但是,我将如何以编程方式为每个用户定义的活动对象创建一个计时器? 如何让程序检测到是否已经创建了计时器?

我一直在这里和谷歌搜索,但到目前为止,我没有遇到对我有意义的事情。 我还在学习C#,所以对你们来说有意义的人可能还不会对我有意义。 :)

我希望我已经解释了我需要的东西,如果你没有得到我,请让我澄清一下。

编辑:

也许我还应该提一下,所提到的字典也会保存到XML文件中,以便用户可以随时获取他们所做的所有设置。

编辑2:

@hatchet我想知道这是否有效。 我试图让它工作,但是碰到了一些困难(因为我缺乏经验,并且不完全理解你的伪代码。我得到错误,一些我可以解决,还有一些我无法(我没想到完全正常工作的代码,不用担心))。

此外,用户应该能够修改计时器。 在mainform中,有几个文本框和三个按钮。 表单用于发送消息。 用户可以选择手动发送消息,将消息添加到计时器或编辑计时器。

当用户点击手动按钮时,消息会一次性传递给所有接收者。 如果将消息添加到计时器,则会弹出一个新子表单,他们可以在其中设置以下详细信息: string名称(定时器) DateTime Start_date CheckBox结束 DateTime End_date NumericUpDown秒(最小值15分钟) Combobox分钟,小时,天 复选框激活

当用户将消息添加到计时器时,TimerSettings以sting,Object(我的自定义对象包含所有细节)的形式进入字典。

如果他们点击主窗体上的修改按钮,则认为在打开子窗体之前,程序会查找相应的定时器(主窗口有一个带有所有添加定时器的组合框),停止定时器然后打开子表单,让用户编辑详细信息。

在子窗体上也是一个删除按钮,以便用户可以删除定时器。

添加或修改计时器时,mainform会捕获它并将更改写入XML文件和组合框。 如果已经存在此消息的计时器并且没有创建,或者如果有则重新启动计时器,那么它应该在这里查看。

我不知道如何让你的解决方案为此工作。 根据接收器的数量,发送消息的过程需要30秒到5分钟(不能超过42个(程序是另一个程序的接口,不允许超过42个接收器))。

我知道几个计时器可能是一个问题,但我怀疑任何用户都需要超过10个计时器,所以可能有一个内置的限制,比如15个计时器。

2 个答案:

答案 0 :(得分:1)

我不确定计时器在这种方法上的扩展程度。可能值得研究管理这些事件的其他方法。正如@hatchet刚发表评论一样,你可以为下一个事件设置一个计时器..通过这种方法,你可以在运行时设置下一个。

另一种可能性是使用数据库和计时器,该计时器每隔<小时间段&gt;运行。以正确的时间戳执行所有操作。

答案 1 :(得分:0)

这是一种伪代码C#,传达了这个想法。我已经完成了同样的事情,但是有足够的小细节是不同的,粘贴代码会让人感到困惑。因此,这个半代码有望与实际代码保持足够接近,以向我展示我对您的问题的评论意味着什么。

假设你有这样的课程

public delegate void Work();

public class TimedThing {
    public int IntervalSecs;
    public DateTime NextFiring;
    public event Work OnWork;        
}

然后你有一个控制器类

public class TimedGroup {
    TimedThing[] things;
    System.Timers.Timer timer;

    public TimedGroup() {
        this.timer = new System.Timers.Timer();
        this.timer.AutoReset = false;
        this.timer.Elapsed += TimerFired;
    }
            ...
    // some methods for adding and removing TimerThings
            ...
    public void Start() {
        this.timer.Interval = 1; // just to get things started
        this.timer.Enabled = true;
    }
    public void Stop() {
        this.timer.Enabled = false;
    }
    private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) {
        DateTime now = DateTime.Now;
        // let's have timer fire at least as frequently as every 5 minutes
        // if we need to have it fire sooner than that, it will get set below
        DateTime next = now.AddMinutes(5); 
        foreach(var thing in this.things) {
            if (thing.nextFiring <= now) {
                var task = Task.Factory.StartNew(() => DoWork(thing));
                thing.NextFiring = thing.NextFiring.AddSeconds(thing.IntervalSeconds);
                // or maybe this is more appropriate
                // thing.NextFiring = Now.AddSeconds(thing.IntervalSecs);
            }
            if (thing.NextFiring < next) next = thing.NextFiring;
        }
        // set the timer to fire whenever the next soonest work needs to be done
        this.Timer.Interval = (next - now).TotalMilliseconds;
        this.Timer.Enabled = true;
    }
    private void DoWork(TimedThing thing) {
        thing.Work();
    }
}

尽管必须要处理这些细节,但有许多细节必须处理,无论你是使用计时器还是单个计时器来处理所有这些细节。例如,如果一件物品的工作通常需要10秒钟,但有时可能需要60秒,并且它们的时间间隔设定为45秒。有时下一次射击会想要再次运行该工作,尽管之前的射击开始时仍在运行。这可能是也可能不是可取的,这取决于这些事情正在做什么样的工作。如果不需要,您必须添加对生成的任务的一些监视,以便您知道是否需要跳过工作,因为之前的工作尚未完成。另一件事是编码优雅的下降。当你将timer.Enabled设置为false(或者timer.Stop()...这是同一件事)时,即使你停止了计时器,也会有一段短暂的时间,即计时器事件仍然可以触发(参见{ {3}})。这可能会导致一些奇怪的行为/错误。