Обновление формы от фонового работника - PullRequest
0 голосов
/ 04 мая 2019

Я хотел бы обновить метку и удалить строку из сетки из фонового рабочего.Я сообщал о прогрессе, но заметил, что событие выполнения отчета не запускается сразу, и обнаружил, что мой второй отчет о выполнении был выполнен до того, как было обработано первое событие.

Чтобы дождаться возникновения события, я подумал об использованиисобытие автоматического сброса для приостановки выполнения (waitone), при этом для события progress задано значение, позволяющее фоновому рабочему продолжить выполнение.

Затем я подумал, что вполне возможно, что событие может сработать до ожидания.

Какой лучший способ справиться с этим?Изменить: в соответствии с предложением Патрика Туччи, я нашел следующую ссылку ... https://social.msdn.microsoft.com/Forums/en-US/cbd99f1f-ac56-440b-8fbd-093534e11d69/how-do-i-update-the-gui-during-execution-of-a-task?forum=csharpgeneral В этой ссылке находится этот код (я немного исправил) ...

private void button1_Click(object sender, EventArgs e)
            {
                var uiContext = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();
                // Start a task - this runs on the background thread...
                System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew(() =>
                {
                    for (int i = 1; i < 5; i++)
                    {
                        Console.WriteLine("A i is " + i.ToString());
                        System.Threading.Thread.Sleep(2000);
                        System.Threading.Tasks.Task.Factory.StartNew(() =>
                        {
                            Console.WriteLine("B i is " + i.ToString());
                            textBox1.Text = "Delay " + i.ToString() + " has completed";
                        }, System.Threading.CancellationToken.None, System.Threading.Tasks.TaskCreationOptions.None, uiContext);

                        //textBox1.Text = "Delay " + i.ToString() + " has completed";
                    }
                },  );
                MessageBox.Show("boom!");
            }

Однако,вышесказанное мне не понятно ... Почему первый Task.Factory.StartNew считается фоновой задачей?Оператор окна сообщения (бум) немедленно срабатывает.Есть ли способ, чтобы это не продолжалось до завершения асинхронной задачи?И по какой-то причине «Задержка 1» никогда не отображается, т. Е. A2 не выводится на консоль отладки: только A1 B1 B2 C1 C2 и т. Д.?

1 Ответ

0 голосов
/ 05 мая 2019

Хорошо, это была моя ошибка, чтобы понять, как работает autoresetevent.

Перед запуском цикла в фоновом рабочем режиме я все равно должен AE.Reset . Это означает, что следующее WaitOne заставит рабочего спать.

В цикле я должен ReportProgress как обычно, за которым следует WaitOne . WaitOne заставляет рабочего спать, но только если AE был Reset . Если AE был Set , рабочий продолжит как обычно.

В событии ProgressChanged я должен обновить обычные элементы управления графическим интерфейсом, а затем AE.Set , чтобы разрешить спящему рабочему в состоянии WaitOne продолжить.

Если по какой-либо причине AE.WaitOne выполняется ПОСЛЕ AE.Set , работник ничего не ждет.

Наконец, ожидал ли работник или нет, AE автоматически сбрасывается, что означает, что WaitOne снова будет спать.

В основном ... Выполнение Сброс вызывает следующий WaitOne для сна. Выполнение Set освобождает поток в WaitOne . Если в WaitOne ничего не установлено, Set немедленно освобождает NEXT WaitOne . Выполнение WaitOne автоматически Сброс .

Все немного сбивает с толку, и документация не самая лучшая. Но я понял.

Я буду придерживаться фонового работника, потому что, на мой взгляд, это гораздо более простые задачи.

...