Вопрос

Я пытаюсь выяснить лучший способ обрабатывать фоновый механизм, который срабатывает на кликах радиопередачи. Я создал очень простую форму с 3 радиоукоминами и меткой. Каждое из радиопередач разделяет одно и то же событие Radiobutton_checkedChangedChanged. Если событие завершится, я обновляю метку на «Complete». Если вы нажмете другую кнопку переключателя до завершения события, затем обновите метку для отмены. Ниже приведен код, который я написал в этом быстром примере. Хотя приложение имеет тенденцию проводить, как ожидалось, моя проблема - это использование Application.Dovents. Каковы мои альтернативы этому. По понятным причинам я не могу спать во время Isbusy. Я собираюсь все это неправильно или есть лучший способ сделать это? Спасибо, Поко

private void radioButton_CheckedChanged(object sender, EventArgs e)
{
  RadioButton rb = sender as RadioButton;
            if (rb.Checked)
            {
                if (backgroundWorker1.IsBusy)
                {
                    backgroundWorker1.CancelAsync();
                    while (backgroundWorker1.IsBusy)
                        Application.DoEvents();
                }

                backgroundWorker1.RunWorkerAsync();
            }
        }

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            for (int i = 0; i < 100 && !worker.CancellationPending; ++i)
                Thread.Sleep(1);

            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                label1.Text = "Canceled";
            else
                label1.Text = "Complete";
        }
Это было полезно?

Решение

Вы должны переместить код, который должен работать, когда Projan Worker завершится в RunWorkerCleplet, который. В псевдо-коде:

private void radioButton_CheckedChanged(object sender, EventArgs e)
{
    // ...

    if (backgroundWorker1.IsBusy)
    {
        backgroundWorker1.CancelAsync();
        addJobToQueue();   // Don't wait here, just store what needs to be executed.
    } else {
        backgroundWorker1.RunWorkerAsync();
    } 
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled) {
        label1.Text = "Canceled";
    }
    else {
        label1.Text = "Complete";
    }

    // We've finished! See if there is more to do...
    if (thereIsAnotherJobInTheQueue())
    {
         startAnotherBackgroundWorkerTask();
    }
}

Другие советы

DoEvents не должен быть принят так небрежно. Есть лучшие способы. Один из самых хороших описано здесь, так. Отказ Этот ответ, вероятно, лучше всего для вас.

Следовательно, ваше решение становится:

private AutoResetEvent _resetEvent = new AutoResetEvent(false);

private void radioButton_CheckedChanged(object sender, EventArgs e)
{
    RadioButton rb = sender as RadioButton;
    if (rb.Checked)
    {
        if (backgroundWorker1.IsBusy)
        {
            backgroundWorker1.CancelAsync();
            _resetEvent.WaitOne(); // will block until _resetEvent.Set() call made
        }

        backgroundWorker1.RunWorkerAsync();
    }
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    for (int i = 0; i < 100 && !worker.CancellationPending; ++i)
        Thread.Sleep(1);

    if (worker.CancellationPending)
    {
        e.Cancel = true;
    }
    _resetEvent.Set();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top