0

I created a DataGridView (Building queue) which can be filled by the user. The user has to insert the time [Textbox H and M] it has to wait. After selecting the buildings and adding them to the queue, the user can press start [Button Start/Stop] and the countdown still start for a maximum of 4 buildings at a time [Textbox named Builders].

Added buildings to the queue: First - Buildings in queue

Pressed Start. 4 countdowns running. 5th one is waiting. CountDown of 4 timers

After the first timer hits zero, the row of that timer will be deleted. The program isn't using the right timers. (There was a bit of delay between the screenshots.) The first row has been duplicated. The first row timer has stopped working. and the others are still counting down. But the 5th row, disappeared. After first timer hits zero

I want the program to be able to continue with the next building countdown whenever one of the four countdowns is finished.

public void TimerFirstRow_Tick(object sender, EventArgs e)
        {

            if (time0 > 0 && this.dataGridView1.Rows.Count > 0)
            {
                time0--;
                this.dataGridView1.Rows[0].Cells[2].Value = string.Format("00:{0}:{1}", time0 / 60, time0 % 60);
            }
            else
            {
                timer_0.Stop();

            }

And I think here is the mistake / error, the place of the countdown is hardcoded into the Timer Tick event code.

The start button code:

 private void StartButton_Click(object sender, EventArgs e)
    {
        QueueMax = this.dataGridView1.Rows.Count;
        
        if (MaxBuild.Text == "")
        {
            label3.Text = "Fill MaxBuilders:";
        }
        else
        {
            MaxBuilder = int.Parse(MaxBuild.Text);
        }
        if (QueueMax >= MaxBuilder)
        {
            if (!timerB)
            {

                if (QueueMax > 0)
                {
                    if (QueueMax == 1)
                    {
                        string xycoord = this.dataGridView1.Rows[0].Cells[3].Value.ToString();
                        string[] xyList = xycoord.Split(':');
                        int x = int.Parse(xyList[0]);
                        int y = int.Parse(xyList[1]);
                        this.WindowState = FormWindowState.Minimized;
                        Thread.Sleep(500);
                        SendKeys.Send("%+{TAB}");
                        Klikken(x, y);
                        this.WindowState = FormWindowState.Normal;

                        
                        time0 = Convert.ToInt32(this.dataGridView1.Rows[0].Cells[2].Value) * 60;
                        timer_0 = new DispatcherTimer();
                        timer_0.Interval = new TimeSpan(0, 0, 1);
                        timer_0.Tick += TimerFirstRow_Tick;
                        timer_0.Start();
                        StartButton.Text = "Stop";
                        timerB = true;
                    }

                    else if (QueueMax == 2)
                    {
                        string xycoord = this.dataGridView1.Rows[0].Cells[3].Value.ToString();
                        string[] xyList = xycoord.Split(':');
                        int x = int.Parse(xyList[0]);
                        int y = int.Parse(xyList[1]);
                        this.WindowState = FormWindowState.Minimized;
                        Thread.Sleep(500);
                        SendKeys.Send("%+{TAB}");
                        Klikken(x, y);
                        string xycoord1 = this.dataGridView1.Rows[1].Cells[3].Value.ToString();
                        string[] xyList1 = xycoord.Split(':');
                        int x1 = int.Parse(xyList[0]);
                        int y1 = int.Parse(xyList[1]);
                        Klikken(x1, y1);
                        this.WindowState = FormWindowState.Normal;



                        time0 = Convert.ToInt32(this.dataGridView1.Rows[0].Cells[2].Value) * 60;
                        time1 = Convert.ToInt32(this.dataGridView1.Rows[1].Cells[2].Value) * 60;
                        timer_0 = new DispatcherTimer();
                        timer_1 = new DispatcherTimer();
                        timer_0.Interval = new TimeSpan(0, 0, 1);
                        timer_1.Interval = new TimeSpan(0, 0, 1);
                        timer_0.Tick += TimerFirstRow_Tick;
                        timer_1.Tick += timer2_Tick_1;
                        timer_0.Start();
                        timer_1.Start();
                        StartButton.Text = "Stop";
                        timerB = false;
                    }
                    else if (QueueMax == 3)
                    {
                        string xycoord = this.dataGridView1.Rows[0].Cells[3].Value.ToString();
                        string[] xyList = xycoord.Split(':');
                        int x = int.Parse(xyList[0]);
                        int y = int.Parse(xyList[1]);
                        this.WindowState = FormWindowState.Minimized;
                        Thread.Sleep(500);
                        SendKeys.Send("%+{TAB}");
                        Klikken(x, y);
                        string xycoord1 = this.dataGridView1.Rows[1].Cells[3].Value.ToString();
                        string[] xyList1 = xycoord.Split(':');
                        int x1 = int.Parse(xyList[0]);
                        int y1 = int.Parse(xyList[1]);
                        Klikken(x1, y1);

                        string xycoord2 = this.dataGridView1.Rows[2].Cells[3].Value.ToString();
                        string[] xyList2 = xycoord.Split(':');
                        int x2 = int.Parse(xyList[0]);
                        int y2 = int.Parse(xyList[1]);
                        Klikken(x1, y1);
                        this.WindowState = FormWindowState.Normal;

                        time0 = Convert.ToInt32(this.dataGridView1.Rows[0].Cells[2].Value) * 60;
                        time1 = Convert.ToInt32(this.dataGridView1.Rows[1].Cells[2].Value) * 60;
                        time2 = Convert.ToInt32(this.dataGridView1.Rows[2].Cells[2].Value) * 60;
                        timer_0 = new DispatcherTimer();
                        timer_1 = new DispatcherTimer();
                        timer_2 = new DispatcherTimer();
                        timer_0.Interval = new TimeSpan(0, 0, 1);
                        timer_1.Interval = new TimeSpan(0, 0, 1);
                        timer_2.Interval = new TimeSpan(0, 0, 1);
                        timer_0.Tick += TimerFirstRow_Tick;
                        timer_1.Tick += timer2_Tick_1;
                        timer_2.Tick += timer3_Tick;
                        timer_0.Start();
                        timer_1.Start();
                        timer_2.Start();
                        StartButton.Text = "Stop";
                        timerB = false;
                    }
                    else if (QueueMax >= 4)
                    {
                        string xycoord = this.dataGridView1.Rows[0].Cells[3].Value.ToString();
                        string[] xyList = xycoord.Split(':');
                        int x = int.Parse(xyList[0]);
                        int y = int.Parse(xyList[1]);
                        this.WindowState = FormWindowState.Minimized;
                        Klikken(x, y);


                        string xycoord1 = this.dataGridView1.Rows[1].Cells[3].Value.ToString();
                        string[] xyList1 = xycoord.Split(':');
                        int x1 = int.Parse(xyList[0]);
                        int y1 = int.Parse(xyList[1]);
                        Thread.Sleep(500);
                        SendKeys.Send("%+{TAB}");
                        Klikken(x1, y1);


                        string xycoord2 = this.dataGridView1.Rows[2].Cells[3].Value.ToString();
                        string[] xyList2 = xycoord.Split(':');
                        int x2 = int.Parse(xyList[0]);
                        int y2 = int.Parse(xyList[1]);
                        Klikken(x1, y1);



                        string xycoord3 = this.dataGridView1.Rows[3].Cells[3].Value.ToString();
                        string[] xyList3 = xycoord.Split(':');
                        int x3 = int.Parse(xyList[0]);
                        int y3 = int.Parse(xyList[1]);
                        Klikken(x1, y1);
                        this.WindowState = FormWindowState.Normal;

                        time0 = Convert.ToInt32(this.dataGridView1.Rows[0].Cells[2].Value) * 60;
                        time1 = Convert.ToInt32(this.dataGridView1.Rows[1].Cells[2].Value) * 60;
                        time2 = Convert.ToInt32(this.dataGridView1.Rows[2].Cells[2].Value) * 60;
                        time3 = Convert.ToInt32(this.dataGridView1.Rows[3].Cells[2].Value) * 60;
                        timer_0 = new DispatcherTimer();
                        timer_1 = new DispatcherTimer();
                        timer_2 = new DispatcherTimer();
                        timer_3 = new DispatcherTimer();
                        timer_0.Interval = new TimeSpan(0, 0, 1);
                        timer_1.Interval = new TimeSpan(0, 0, 1);
                        timer_2.Interval = new TimeSpan(0, 0, 1);
                        timer_3.Interval = new TimeSpan(0, 0, 1);
                        timer_0.Tick += TimerFirstRow_Tick;
                        timer_1.Tick += timer2_Tick_1;
                        timer_2.Tick += timer3_Tick;
                        timer_3.Tick += timer4_Tick;
                        timer_0.Start();
                        timer_1.Start();
                        timer_2.Start();
                        timer_3.Start();
                        StartButton.Text = "Stop";
                        timerB = false;
                    }
                }
            }
            else
            {
                if (timer_0.IsEnabled)
                {
                    timer_0.Stop();
                    timerB = false;
                    StartButton.Text = "Start";
                } else if (timer_1.IsEnabled)
                {
                    timer_0.Stop();
                    timer_1.Stop();
                    timerB = false;
                    StartButton.Text = "Start";
                } else if (timer_2.IsEnabled)
                {
                    timer_0.Stop();
                    timer_1.Stop();
                    timer_2.Stop();
                    timerB = false;
                    StartButton.Text = "Start";
                } else if (timer_3.IsEnabled)
                {
                    timer_0.Stop();
                    timer_1.Stop();
                    timer_2.Stop();
                    timer_3.Stop();
                    timerB = false;
                    StartButton.Text = "Start";

                }

            }
        }
    } //Start Timers
Zeeebass
  • 37
  • 8
  • 2
    Pictures of code will attract downvotes. Paste it as text. We probably need to see more timer code, especially since you are talking about adding and deleting timers. – LarsTech Oct 08 '20 at 21:23
  • Fixed that! Should've known haha – Zeeebass Oct 08 '20 at 22:08
  • 2
    Your DataGridView indicates WinForms, your DispatcherTimer indicates WPF. I'm guessing this is WinForms, in which case, you really should use the WinForms Timer instead. See [Comparing Timer with DispatcherTimer](https://stackoverflow.com/q/1111645/719186) – LarsTech Oct 08 '20 at 22:15
  • And declare timers global to the 4 cases. Start, stop or reset the timers in the code , that way it will be cleaner to troubleshoot. – Shemeer BK Oct 08 '20 at 22:27

1 Answers1

1

I recommend using a single timer, and then subtracting the elapsed time from the original Waiting Time. The important code is in the timer_Tick method:

public class BuildingForm : Form {

    DataGridView dgv = new DataGridView();
    DataTable table = new DataTable();

    Button btnRemoveUpgrade = new Button { Text = "Remove Upgrade" };
    Button btnAddBuilding = new Button { Text = "Add Building" };
    Button btnStart = new Button { Text = "Start" };
    Button btnUpgradeBuilding = new Button { Text = "Upgrade Building" };
    Label lbBuilders = new Label { Text = "Builders:", AutoSize = true, Anchor = AnchorStyles.Bottom | AnchorStyles.Left };
    Label lbWaitTime = new Label { Text = "Wait Time In:", AutoSize = true, Margin = new Padding(0, 20, 0, 0), Anchor = AnchorStyles.Bottom };
    Label lbHours = new Label { Text = "H:", AutoSize = true, Anchor = AnchorStyles.None };
    Label lbMinutes = new Label { Text = "M:", AutoSize = true, Anchor = AnchorStyles.None };
    NumericUpDown nudHours = new NumericUpDown { Minimum = 0, Maximum = 99, Value = 0, Increment = 1, AutoSize = true };
    NumericUpDown nudMinutes = new NumericUpDown { Minimum = 0, Maximum = 59, Value = 1, Increment = 1, AutoSize = true };
    NumericUpDown nudBuilders = new NumericUpDown { Minimum = 1, Maximum = 9999, Value = 4, Increment = 1, AutoSize = true };
    //---
    Timer timer = new Timer { Interval = 1000 };
    DateTime utcStartTime = DateTime.MinValue;
    DataColumn colBuilding;
    DataColumn colToLevel;
    DataColumn colWaitingTime;
    DataColumn colXY;
    List<Data> dataList = new List<Data>();

    public BuildingForm() : base() {
        this.Size = new Size(800, 600);
        this.StartPosition = FormStartPosition.CenterScreen;

        dgv.DataSource = table;
        dgv.Dock = DockStyle.Fill;
        dgv.AllowUserToAddRows = false;

        FlowLayoutPanel panel2 = new FlowLayoutPanel { FlowDirection = System.Windows.Forms.FlowDirection.LeftToRight, WrapContents = false, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };
        panel2.Controls.AddRange(new Control[] { lbHours, nudHours, lbMinutes, nudMinutes });

        TableLayoutPanel panel1 = new TableLayoutPanel { Dock = DockStyle.Fill, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };       
        panel1.Controls.Add(btnRemoveUpgrade, 0, 0); panel1.Controls.Add(btnAddBuilding, 1, 0);
        panel1.Controls.Add(btnStart, 0, 1); panel1.Controls.Add(btnUpgradeBuilding, 1, 1);
        panel1.Controls.Add(lbBuilders, 0, 2); panel1.Controls.Add(lbWaitTime, 1, 2); panel1.Controls.Add(new Control(), 2, 2);
        panel1.Controls.Add(nudBuilders, 0, 3); panel1.Controls.Add(panel2, 1, 3);

        TableLayoutPanel panel = new TableLayoutPanel { Dock = DockStyle.Fill };
        panel.GrowStyle = TableLayoutPanelGrowStyle.AddColumns;
        panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 1f));
        panel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
        panel.Controls.Add(dgv, 0, 0);
        panel.Controls.Add(panel1, 1, 0);
        Controls.Add(panel);

        Size sz = btnUpgradeBuilding.PreferredSize;
        sz.Width += 20;
        sz.Height += 20;
        foreach (Control c in new Control[] { btnRemoveUpgrade, btnAddBuilding, btnStart, btnUpgradeBuilding }) {
            c.Size = sz;
        }

        colBuilding = table.Columns.Add("Building");
        colToLevel = table.Columns.Add("To Level", typeof(int));
        colWaitingTime = table.Columns.Add("Waiting Time:", typeof(TimeSpan));
        colXY = table.Columns.Add("X:Y");

        table.Rows.Add("Test", 11, TimeSpan.FromMinutes(1), "100:100");
        table.Rows.Add("Test", 11, TimeSpan.FromMinutes(10), "100:100");
        table.Rows.Add("Test", 11, TimeSpan.FromMinutes(20), "100:100");
        table.Rows.Add("Test", 11, TimeSpan.FromMinutes(30), "100:100");
        table.Rows.Add("Test", 11, TimeSpan.FromMinutes(90), "100:100");

        dgv.BindingContext = new System.Windows.Forms.BindingContext(); // forces dgv columns to be created
        dgv.Columns[colWaitingTime.Ordinal].DefaultCellStyle.Format = "hh':'mm':'ss";

        btnStart.Click += btnStart_Click;
        timer.Tick += timer_Tick;
    }

    private void timer_Tick(object sender, EventArgs e) {
        DateTime utcNow = DateTime.UtcNow;
        TimeSpan ellapsed = utcStartTime - utcNow;
        for (int i = dataList.Count - 1; i >= 0; i--) {
            Data d = dataList[i];
            TimeSpan ts = d.tsOrig.Add(ellapsed);
            if (ts.Ticks <= 0) {
                table.Rows.Remove(d.row);
                dataList.RemoveAt(i);
            }
            else {
                d.row[colWaitingTime] = ts;
            }
        }
        dgv.Invalidate();
    }

    private class Data {
        public DataRow row;
        public TimeSpan tsOrig;
    }

    void btnStart_Click(object sender, EventArgs e) {
        int numBuilders = (int) nudBuilders.Value;
        for (int i = 0; i < numBuilders && i < table.Rows.Count; i++) {
            Data d = new Data { row = table.Rows[i], tsOrig = (TimeSpan) table.Rows[i][colWaitingTime] };
            dataList.Add(d);
        }

        utcStartTime = DateTime.UtcNow;
        timer.Start();
        btnStart.Enabled = false;
    }

    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
        if (disposing)
            timer.Dispose();
    }
}
Loathing
  • 5,109
  • 3
  • 24
  • 35