Scott_fro
Scott_fro

Reputation: 11

switching from different timers c#

I'm creating an Windowns phone 8 app(c#), its a countdown interval timer, so there is prepare time(10 sec), work time(20 sec), rest time(10 sec). I have these variables

  `TimeSpan prepInterval = new TimeSpan(0, 0, 0, 10);
   TimeSpan workInterval = new TimeSpan(0, 0, 0, 20);
   TimeSpan restInterval = new TimeSpan(0, 0, 0, 10);`

I can't wrap my head around having them implementing them one after another when they hit 0. So when prepare time is done, the work timer is to start and when thats finised, the rest timer is to start.

Upvotes: 0

Views: 71

Answers (2)

Icepickle
Icepickle

Reputation: 12796

If you would like to have some more broken down logic in all of this, maybe you can create some classes based on a simple interface, like the following:

interface ITimerAction
{
    int Seconds { get; set; }
    bool Started { get; }
    bool Completed { get; }
    void OnStart();
    void OnComplete();
}

interface ITimerActionList
{
    void Add(ITimerAction action);
    void Work();
    event EventHandler OnCompletedEvent;
}

This would then allow you to create an abstract TimerAction class, and TimerActionList

abstract class TimerAction : ITimerAction
{
    public virtual int Seconds
    {
        get;
        set; 
    }

    public virtual bool Completed
    {
        get;
        protected set;
    }

    public virtual bool Started
    {
        get;
        protected set; 
    }

    public abstract void OnStart();

    public abstract void OnComplete();
}

class TimerActionList : ITimerActionList
{
    public event EventHandler OnCompletedEvent;

    private readonly IList<ITimerAction> actions = new List<ITimerAction>();

    private bool working = false;
    private Thread myThread;

    public void Add(ITimerAction action)
    {
        if (working)
        {
            throw new InvalidOperationException("Cannot add new timers when work is already in progress");
        }
        actions.Add(action);
    }

    protected virtual void DoWork()
    {
        working = true;
        int currentStep = 0, maxSteps = actions.Count;
        while (currentStep < maxSteps)
        {
            ITimerAction action = actions[currentStep];
            if (!action.Started)
            {
                action.OnStart();
            }
            if (action.Completed)
            {
                currentStep++;
                continue;
            }
            if (action.Seconds == 0)
            {
                action.OnComplete();
                continue;
            }
            action.Seconds--;
            Thread.Sleep(1000);
        }
        Completed();
    }

    public void Work()
    {
        if (working)
        {
            throw new InvalidOperationException("Already running!");
        }
        working = true;
        myThread = new Thread(DoWork);
        myThread.Start();
    }

    protected virtual void Completed()
    {
        myThread = null;
        working = false;
        actions.Clear();
        var local = OnCompletedEvent;
        if (local != null)
        {
            local.Invoke(this, EventArgs.Empty);
        }
    }
}

You could then write the classes that inherit from the TimerAction class, that could handle an action before and after the timer ran through :)

class PrepareTimer : TimerAction
{
    public override void OnStart()
    {
        Console.WriteLine("Preparing");
        Started = true;
    }

    public override void OnComplete()
    {
        Console.WriteLine("Prepare ready");
        Completed = true;
    }
}

class WorkTimer : TimerAction
{
    public override void OnStart()
    {
        Console.WriteLine("Working");
        Started = true;
    }

    public override void OnComplete()
    {
        Console.WriteLine("Work ready");
        Completed = true;
    }
}

class CoolDownTimer : TimerAction
{
    public override void OnStart()
    {
        Console.WriteLine("Cooling down");
        Started = true;
    }

    public override void OnComplete()
    {
        Console.WriteLine("Cooldown ready");
        Completed = true;
    }
}

And then you could test the code as such

static void Main(string[] args)
{
    bool done = false;
    ITimerActionList mylist = new TimerActionList();
    mylist.Add(new PrepareTimer { Seconds = 1 });
    mylist.Add(new WorkTimer { Seconds = 2 });
    mylist.Add(new CoolDownTimer { Seconds = 1 });

    mylist.OnCompletedEvent += (sender, e) =>
    {
        done = true;
    };
    mylist.Work();
    while (!done)
    {
        // timer is running
    }
    Console.WriteLine("Done!");
}

(Console program, but i guess that also goes to demonstrate?)

Upvotes: 1

Dmitry Popov
Dmitry Popov

Reputation: 398

Here's an example based on deathismyfriend's and Hans Passant's suggestions:

var start = new DateTime();
var stage = 0;

var timer = new System.Timers.Timer(100);

timer.Elapsed += (s, e) =>
{
    var elapsed = DateTime.Now - start;
    int duration = stage == 1 ? 20 : 10;

    if (elapsed.TotalSeconds > duration)
    {
        start = DateTime.Now;
        stage++;

        if (stage > 2)
            timer.Stop();
    }
};

start = DateTime.Now;
stage = 0;

timer.Start();

Upvotes: 0

Related Questions