1

Мне нужно сделать таймер на 25 минут, который по истечению времени закрывает форму. При этом должен быть progressBar который отображает эти 25 минут. Пробую так:

private void Form2_Load(object sender, EventArgs e)
        {
            progressBar1.Maximum = 25 * 60 * 1000;
            Timer MyTimer = new Timer();
            MyTimer.Interval = (25 * 60 * 1000); // 25 mins
            MyTimer.Tick += new EventHandler(MyTimer_Tick);
            MyTimer.Start();
        }
    private void MyTimer_Tick(object sender, EventArgs e)
    {
        count++;
        if (count <= 25 * 60 * 1000)
            progressBar1.Value = count;
        MessageBox.Show("The form will now be closed.", "Time Elapsed");
        this.Close();
    }

Но по результату этого кода progressBar ничего не отображает. В чём ошибка? И можно ли progressBar установить вертикально?

Kromster
  • 13,809

2 Answers2

2

Предлагаю такой варинат:

    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            Shown += Form1_Shown;
        }
    private async void Form1_Shown(object sender, EventArgs e) {
        progressBar1.Value = 100;
        for (int i = 25 * 60; i > 0; i--) {
            progressBar1.Value = i * 100 / (25 * 60);
            await Task.Delay(1000);
        }
        Close();
    }
}

Без таймера. С асинк-авэйтами. Очень коротенечко :-)

S.H.
  • 11,065
  • 1
  • 24
  • 46
  • Большое спасибо, работает! А не подскажете ещё, как реализовать тоже самое, только так: у меня есть три радио-кнопки с 25,20,15 минут, как от их выбора сделать соотвевствующий таймер? – Ярослав Овчар Apr 09 '21 at 19:16
  • 1
    Task.Delay дает задержку больше, чем указано. За счет расходов на асинхронность. Нужно корректировать ожидание по часам. Соврет примерно на несколько минут в большую сторону. – aepot Apr 09 '21 at 20:56
  • @aepot - Согласен, нужно скрестить мой пример с работой с TimeSpan из примера tym32767 – S.H. Apr 09 '21 at 20:59
  • 1
    @S.H. Пример, как откорректировать погрешность Task.Delay. Если этот метод скрестить с токеном отмены, получится четкая красивая реализация с возможностью остановки. А то что вы предложили, если форму закрыть раньше времени, через 25 минут оно упадет с исключением при попытке закрыть уже закрытую форму. – aepot Apr 10 '21 at 11:12
  • ...Так как исключения в async void вы не ловите, автор конечно его не увидит, но оно будет с вероятностью 100%, если конечно приложение не будет полностью закрыто раньше. – aepot Apr 10 '21 at 11:25
2

Пример без таймеров. Также важно отметить, что тут время не завсит от количества вызовов, оно зависит только от времени. При желаении, можно его ещё чуть улучить и сделать точнее

public class MyForm : Form
{
    public MyForm()
    {
        this.Width = 500;
        this.Height = 500;
        var button = new Button() { Text = "Close me in 20 secs", Width = 200, Height = 50 };
        var pg = new ProgressBar() { Maximum = 100, Width = 200, Height = 50, Top = 50 };
    this.Controls.Add(button);
    this.Controls.Add(pg);

    button.Click += async (sender, args) =>
    {   
        var startTimeUtc = DateTime.UtcNow;
        var endTimeUtc = startTimeUtc.AddSeconds(20);

        var duration = endTimeUtc - startTimeUtc;

        while (endTimeUtc > DateTime.UtcNow)
        {
            await Task.Delay(1000); // refresh rate 

            var remaining = endTimeUtc - DateTime.UtcNow;
            int progress = (int)(100.0 - 100.0 * remaining.TotalSeconds / duration.TotalSeconds);

            pg.Value = progress;
        }

        this.Close();
    };
}

}

...

Добавляйте по вкусу опции и прчие вещи, вплоть до отмены операции.

tym32167
  • 32,857