Как я могу остановить поток на пользовательском контроле, когда форма закрыта - PullRequest
3 голосов
/ 28 апреля 2011

У меня есть пользовательский элемент управления со следующим кодом:

private Thread updateProgress;
private void FileUploadingScreen_Load(object sender, EventArgs e)
{
    updateProgress = new Thread(UpdateProgressBar);
    updateProgress.Start();
}
private bool run = true;
private void UpdateProgressBar()
{
    while (run)
    {
        Thread.Sleep(100);
        if(run)
        {
           progressBar1.Invoke(new Action(() =>
           {
               if (progressBar1.Value >= 100)
               {
                    progressBar1.Value = 1;
                    progressBar1.Step = 1;
               }
               progressBar1.PerformStep();
           }));
        }
    }
}

public void StopProgressBar()
{
    run = false;
}

в родительской форме у меня есть:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    userControl.StopProgressBar();
}

когда я закрываю форму нажатием X, в строке progressBar1.Invoke появляется следующая ошибка.

Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

Я думал, что установка run в false в событии form_closing остановит это. Как я могу это исправить? Моя главная цель - иметь прогресс-бар, который продолжает двигаться, чтобы показать, что что-то происходит все еще. Есть ли лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 28 апреля 2011

Вы можете использовать это

public void StopProgressBar()
{
    updateProgress.Abort();
}

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

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

Согласно этому обсуждению , изменив метод Dispose элемента управления в Designer.csбезопасен, VS должен уважать эти изменения и не перезаписывать их.

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    //Special handling of started thread
    if (disposing && updateProgress.IsAlive)
    {
        updateProgress.Abort();
    }
    base.Dispose(disposing);
}

При этом вашей родительской форме не нужно явно вызывать StopProgressBar.

0 голосов
/ 28 апреля 2011

Попробуйте

public void StopProgressBar()
{
    run = false;
    updateProgress.Join();
}

Проблема в том, что вы предполагаете, что, как только вы установите для «run» значение false, поток остановится.Происходит то, что Windows продолжает утилизировать окно, пока ваш поток еще выполняется.Это решение блокирует, пока поток не завершит выполнение.

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