0

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

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

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

将 t_num 与 60000(分钟)、3600000(小时)或 86400000 结合起来应该给出正确的间隔。

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

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

我希望我已经解释了我需要足够好的东西,如果你不明白我,请让我澄清一下。

编辑:

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

编辑2:

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

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

当用户点击手动按钮时,消息会发送给所有接收者一次。如果将消息添加到计时器,则会弹出一个新的子表单,他们可以在其中设置以下详细信息: string Name (of timer) DateTime Start_date CheckBox Ending DateTime End_date NumericUpDown Seconds (最小值为 15 分钟) Combobox Minutes, Hours , 天数复选框激活

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

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

子窗体上还有一个删除按钮,以便用户可以删除计时器。

添加或修改计时器时,mainform 会捕获它并将更改写入 XML 文件和组合框。如果已经有一个用于此消息的计时器并且在没有的情况下创建,或者如果有,则重新启动计时器。

我不确定我应该如何让您的解决方案为此工作。发送消息的过程需要 30 秒到 5 分钟,具体取决于接收器的数量(不能超过 42(该程序是另一个程序的接口,不允许超过 42 个接收器))。

我知道几个计时器可能是一个问题,但我怀疑任何用户都需要超过最多 10 个计时器,因此可能存在一个内置限制,比如说 15 个计时器。

4

2 回答 2

1

我不确定计时器在这种方法下的扩展效果如何。可能值得研究管理这些事件的其他方法。正如@hatchet 刚刚发表的评论一样,您可以为下一个事件设置 1 个计时器。使用这种方法,您可以在它运行时设置下一个计时器。

另一种可能性是使用一个数据库和一个每隔 <small time period> 运行的计时器,它执行所有带有适当时间戳的操作。

于 2012-07-05T02:13:09.263 回答
1

这是一种伪代码 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 秒。有时下一次触发会想要再次运行该工作,尽管在上一次触发时开始的先前工作仍在运行。这可能是可取的,也可能不是可取的,这取决于这些东西在做什么。如果不希望这样做,您必须添加一些对生成的任务的监控,以便您知道是否需要跳过执行工作,因为之前的工作尚未完成。另一件事是编码一个优雅的结束。当你设置定时器。为什么当 Enabled 设置为 false 时 System.Timer.Timer 仍会触发事件?)。这可能会导致一些奇怪的行为/错误。

于 2012-07-05T06:09:21.263 回答