C# timer с ProgressBar

196
21 ноября 2017, 20:33

Натолкнулся на проблему которую не могу решить. Есть обработчик кнопки и в ней код, timer используется как контролл из ToolBox на форме. Обрабатывается таблица Excel, данные записываются в БД, нужен Прогрессбар для визуализации Ниже код:

                timer1.Enabled = true; // Enable the timer.
                timer1.Interval = 5;
                timer1.Tick += new EventHandler(timer1_Tick);
                timer1.Start();//Strart it
                for (int i = 1; i <= 21; i++)
                {
                 //код обработки и записи  в БД
                }
                //конец обработки выборки из таблицы Excel 
                MessageBox.Show("!!!"); 

Текст обработчика timer1:

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (progressBar1.Value != int.Parse(textBox2.Text))
        {
            progressBar1.Value++;
        }
        else
        {
            timer1.Stop();
        }
    }

Но вот какое дело - специально поставил для наглядности интервал 5 миллисекунд, однако MessageBox.Show выскакивает ранее чем вызов обработчика timer. В чем причина?

Answer 1

Ваш код выполняется в потоке UI. При этом все вызовы таймера ставятся в очередь которую этот самый поток UI и разгребает. Вот и получается: пока код не отработает - таймер спит.

Чтобы ваш прогресбар работал - нужно либо наставить в цикле костылей в виде Application.DoEvents(), либо вынести долгую обработку в отдельный поток. Проще всего это сделать при помощи задач (Tasks) а асинхронного программирования:

// метод в котором выполняется этот код надо отметить как асинхронный (async)
timer1.Enabled = true; // Enable the timer.
timer1.Interval = 5;
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();//Strart it
await Task.Run(() => 
{
    // Долгий код
});
MessageBox.Show("!!!"); 

Альтернативный вариант - можно заменить все внешние вызовы (например, обращение к БД) асинхронными операциями, оставшись при этом в потоке UI.

READ ALSO
Создание собственных координат внутри Canvas

Создание собственных координат внутри Canvas

Необходимо задать собственную систему координат в CanvasЗначения X и значения Y не будут одинакового типа

177
Как сделать отправку данных?

Как сделать отправку данных?

есть отправка данных при нажатии enter

303
Импорт фигуры из blender в Three.js

Импорт фигуры из blender в Three.js

Стандартная фигура + post processing в самом блендере

338
Данные из input в реальном времени

Данные из input в реальном времени

Делаю небольшой конвертер величин

289