Ручная остановка отладки с помощью backgroundworker - PullRequest
4 голосов
/ 14 августа 2011

Я пишу проект WPF C # с использованием BackgroundWorker (всплывающее окно с индикатором выполнения).

Я начинаю отладку (клавиша F5), чтобы проверить мою программу.После завершения BackgroundWorker и закрытия всплывающего окна закрытие MainWindow не останавливает процесс отладки автоматически.Я должен вручную нажать Shift + F5 , чтобы остановить отладку.

Я думал BackgroundWorker должен был позаботиться о нити автоматически.Но в любом случае я все еще вызываю backgroundworker.Dispose() и backgroundworker.CancelAsync() в методе RunWorkerCompleted.И все же, при закрытии всплывающего окна и завершении BackgroundWorker мне все еще нужно вручную сделать Shift + F5 , чтобы остановить отладку.

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

ПРИМЕЧАНИЕ: перед тем, как закрыть его, я убедился, что фоновый работник завершил DoWork и завершил его.С помощью всплывающего окна и BackgroundWorker он автоматически прекращает отладку, как только я закрываю главное окно.

[ПРАВКА с кодами]

public partial class MainWindow : Window
{
    BackgroundWorker backgroundworker1 = new BackgroundWorker();

    PopUp pop1 = new PopUp();

public MainWindow()
{
    InitializeComponent();

    backgroundworker1.DoWork += BackgroundWorker_DoWork;
    backgroundworker1.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted;
    backgroundworker1.WorkerReportsProgress = true;
    backgroundworker1.ProgressChanged += BackgroundWorker_ProgressChanged;
    backgroundworker1.WorkerSupportsCancellation = true;
}

private void startBtn_Click(object sender, RoutedEventArgs e)
{
    pop1 = new PopUp();

    int iteration = 0;
    if (int.TryParse(iterationTb1.Text, out iteration))
    {
        pop1.Show();
        backgroundworker1.Dispose();
        backgroundworker1.RunWorkerAsync(iteration);
        outputTb1.Text = "running...";
    }
}

private void cancelBtn_Click(object sender, RoutedEventArgs e)
{
    pop1.Close();
    backgroundworker1.CancelAsync();
}

public static int DoSlowProcess(int iterations, BackgroundWorker worker, DoWorkEventArgs e)
{
    int result = 0;

    for (int i = 0; i <= iterations; i++)
    {
        if (worker != null)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return result;
            }
            if (worker.WorkerReportsProgress)
            {
                int percentComplete = (int)((float)i / (float)iterations * 100);
                worker.ReportProgress(percentComplete);
            }
        }

        Thread.Sleep(100);
        result = i;
    }

    return result;
}


private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var bgw = sender as BackgroundWorker;
    e.Result = DoSlowProcess((int)e.Argument, bgw, e);
}

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
    }
    else if (e.Cancelled)
    {
        outputTb1.Text = "Canceled";
    }
    else
    {
        outputTb1.Text = e.Result.ToString();
        backgroundworker1.CancelAsync();
        backgroundworker1.Dispose();
        pop1.Close();
        pop1.progressBar1.Value = 0;
    }
}

    private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pop1.progressBar1.Value = e.ProgressPercentage;
        pop1.progressLb1.Content = e.ProgressPercentage.ToString();
    }
}

1 Ответ

3 голосов
/ 15 августа 2011

Хорошо, я могу воспроизвести вашу проблему, а также найти причину.

Изменить эту строку:

// PopUp pop1 = new PopUp();  <-- this never-used Win was blocking your close-down.
PopUp pop1 = null;

Поскольку у вас также есть

pop1 = new PopUp();
int iteration = 0;

Создание объектовпросто чтобы инициализировать переменную var и перезаписать ее, это всегда анти-шаблон.В этом случае это на самом деле вредно, потому что вы создаете Window, но никогда не показываете его () или Close ().

Обратите внимание, что фоновый работник не участвует.Не может быть, он использует ThreadPool, а это означает фоновые потоки.Вы можете закрыть приложение с несколькими работниками фона, работающими без проблем.

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