Нужна помощь с потоками -C # Windows Forms - PullRequest
1 голос
/ 21 октября 2010

Я пытаюсь создать поток, который содержит индикатор выполнения формы (просто изображение GIF).Я позвонил StartProgress() прямо перед большим методом.В основном, когда поток запускается, он загружает форму ProgressBar (которую я хочу показывать все время, и просто скрывать, когда она не нужна), и с ProgressActive установленным в true, он должен отображать форму, пока ProgressActive не станет ложным, тогда форма должна быть скрыта (пока прогресс снова не активен).Вот то, что у меня есть, но оно зависает от меня: (

    public static string ProgressInfo="Test";
    public static bool ProgressActive=true;
    public static bool ThreadStarted = false;

    public static void StartProgress()
    {
        while (!ThreadStarted)
        {
            Thread t = new Thread(new ThreadStart(Progress));
            ThreadStarted = true;
            t.Start();
        }

    }
    public static void Progress()
    {
        while (ThreadStarted)
        {

            LoadingBar lb = new LoadingBar();
            lb.Show();
            lb.TopMost = true;
            while (ThreadStarted)
            {
                if (ProgressActive)
                {
                    lb.Visible = true;
                    lb.lblLoadingStatus.Text = ProgressInfo;
                }
                else
                {
                    lb.Visible = false;
                }
                Thread.Sleep(1000);
            }
        }

    }

РЕДАКТИРОВАТЬ: я пытаюсь сделать это в статическом классе.

Ответы [ 4 ]

4 голосов
/ 21 октября 2010

Есть ли причина не использовать BackgroundWorker при использовании .NET 2.0 или выше?

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

1 голос
/ 21 октября 2010

Проблема в том, что вам нужен цикл сообщений, чтобы любой элемент интерфейса работал правильно. Поскольку вы создаете форму в рабочем потоке, цикл сообщений не выполняется. Чтобы создать цикл сообщений, вы должны позвонить Application.Run или Form.ShowDialog, оба из которых блокируют вызовы. Очевидно, что это решение повредит ваш рабочий поток.

Лучше всего создать отдельный поток, предназначенный для запуска цикла сообщений и который может безопасно обрабатывать формы и элементы управления. Пусть рабочий поток периодически публикует информацию о ходе выполнения в переменную, которая может быть разделена между рабочим потоком и потоком интерфейса пользователя. Затем периодически проводите опрос потока пользовательского интерфейса (используя System.Windows.Form.Timer) с этой общей переменной и соответственно обновляйте пользовательский интерфейс.

В качестве примечания, я бы не стал использовать Control.Invoke или Control.BeginInvoke для передачи информации о ходе выполнения в поток пользовательского интерфейса. Ваша ситуация, кажется, оправдывает подход опроса. Причины предпочтения опроса над нажатием:

  • Это нарушает тесную связь между пользовательским интерфейсом и рабочими потоками, которые навязывает Control.Invoke.
  • Он возлагает ответственность за обновление потока пользовательского интерфейса на поток пользовательского интерфейса, к которому он все равно должен принадлежать.
  • Поток пользовательского интерфейса определяет, когда и как часто должно происходить обновление.
  • Нет риска переполнения насоса сообщений пользовательского интерфейса, как в случае с методами маршалинга, инициированными рабочим потоком.
  • Рабочему потоку не нужно ждать подтверждения того, что обновление было выполнено, прежде чем переходить к следующим шагам (т. Е. Вы получаете большую пропускную способность как для пользовательского интерфейса, так и для рабочих потоков).
1 голос
/ 21 октября 2010

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

private object _lock = new object(); //should have class scope

private void ShowProgressControl(EventArgs e)
{
  if (this.InvokeRequired)
  {
    lock (_lock)
    {
      EventHandler d = new EventHandler(ShowProgressControl);
      this.Invoke(d, new object[] { e });
      return;
    }
  }
  else
  {
    //Show your progress bar.
  }
}

Наслаждайтесь!

0 голосов
/ 21 октября 2010

Вы должны создать индикатор выполнения в главном потоке.

Убедитесь, что ваша тяжелая процедура выполняется из другого потока.

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