【问题标题】:Abstract function and timers抽象函数和定时器
【发布时间】:2017-05-16 15:48:01
【问题描述】:

我对继承很陌生。尝试使用静态计时器实现基类。每次时间过去,这个计时器都会调用一个抽象函数。原因是从基类继承的两个类将具有同步的计时器。这是代码

基类:

 public abstract class UIControllers
{
    public enum IndicatorColors
    {
        Green,
        Red,
        Yellow,
        Blue
    }

    private static Timer UITimer;

    public UIControllers()
    {
        EnableUITimer();
    }

    private int intervalInMillis = 500;

    /// <summary>
    /// Enables the timer responsible for UI effect in the GUI. 
    /// </summary>
    private void EnableUITimer()
    {
        if (UITimer != null)
        {
            return;                
        }

        UITimer = new Timer();
        UITimer.Interval = intervalInMillis;
        UITimer.Elapsed += UITimer_Elapsed;
        UITimer.Start();
    }

    private void UITimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        TimeElapsed();
    }

    /// <summary>
    /// The function is being called when the time interval ellapsed
    /// </summary>
    protected abstract void TimeElapsed();

...

派生类:

    protected override void TimeElapsed()
    {
     ....
    }

它仅适用于从基类继承的两个类中的一个(无论哪个类首先实例化,它都适用)。

谢谢

【问题讨论】:

  • 我们需要查看您的完整实施。为我们提供足够的代码来重现和理解问题。
  • 我认为我们无法为您调试........

标签: c# inheritance


【解决方案1】:

在EnableUITimer() 中,如果静态实例已创建,则您挥手告别,因此唯一可以为UITimer 提供事件处理程序的子类实例是创建它的子类实例——如您所见,第一个实例.事件处理程序是一个实例方法,一个委托。

相反,这样做:

private void EnableUITimer()
{
    if (UITimer != null)
    {
        //  If it already exists, give it a handler from this instance. 
        //  Every instance that wants to be notified has to provide its own 
        //  event handler. 
        UITimer.Elapsed += UITimer_Elapsed;
        return;
    }

    UITimer = new Timer();
    UITimer.Interval = intervalInMillis;
    UITimer.Elapsed += UITimer_Elapsed;
    UITimer.Start();
}

【讨论】:

  • 但是它们不会被同步。我创建了一个静态计时器,因为我只需要一个从不同控制器控制 UI 中的某些内容的计时器
  • 所以我现在有点困惑。我知道我的计时器是静态的。我检查 null 的原因是因为我不想“销毁”类之一引用的前一个计时器实例。我的逻辑缺陷在哪里?
  • @M.Levin 缺陷在于UITimer_Elapsed 是代表。它带有自己的this。当第一个子类为UITimer 提供一个事件处理程序时,该事件处理程序只会为提供它的实例调用。想象一下,如果您的表单为 Button 提供了 Click 处理程序。您不希望在单击该按钮时通知每个表单 - 只通知为其提供处理程序的表单。这就是它的工作原理。每个想要从该对象处理该事件的实例都必须显式提供其自己的处理程序。
【解决方案2】:

这部分代码运行 2 次(每个对象实例一次)

    public UIControllers()
    {
        EnableUITimer();
    }

UITimer 在第一次执行时是静态的并且为空,因此所有 EnableUITimer 都在第一个实例上执行。对于第二个实例,UITimer != null 为 true,因此 EnableUITimer 返回而不创建计时器并连接 UITImer_Elasped。

private void EnableUITimer()
{
    if (UITimer != null)
    {
        return; // Exits on second instance
    }

如果计时器已经实例化,您可能想要做的是跳过创建计时器,但仍连接到 Elapsed 事件

private void EnableUITimer()
{
    if (UITimer == null)
    {
        UITimer = new Timer();
        UITimer.Interval = intervalInMillis;
        UITimer.Start();
    }
    UITimer.Elapsed += UITimer_Elapsed;        
}

【讨论】:

    猜你喜欢
    • 2016-11-29
    • 2020-07-01
    • 1970-01-01
    • 2018-12-02
    • 2015-09-26
    • 2014-06-13
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多