2010-07-27 4 views
0

Я пытаюсь создать индикатор прогресса на форме, но по какой-то причине форма на самом деле не видна до тех пор, пока процесс не закончится, и он закрыт, когда процесс завершится (или, другими словами, форма открыта только на мгновение). Как я могу сделать так, чтобы форма появилась в начале процесса?Индикатор прогресса появляется только после завершения работы?

Примечание: мой код может быть не на 100% правильным, я просто пытаюсь сделать его другим, чем мой, по причинам конфиденциальности.

public void SpawnPizzaProgressBarForm(object sender, EventArgs e) 
{ 
    FormPizzaProgressBar Form = new FormPizzaProgressBar(); 
    Form.ShowDialog(); 
} 
... 
public void ProgressBarForm_Load(object sender, EventArgs e) 
{ 
    Pizza = new Pizza(); 
    Pizza.Eat(PizzaEatingProgressBar); 
    this.Close(); 
} 
... 
public void Eat(ProgressBar PizzaEatingProgressBar) 
{ 
    foreach(var Slice in Pizza) 
    { 
     Slice.Clear(); // 
     PizzaEatingProgressBar.Value = (Slice.Index/Pizza.Count())*100 
    } 
} 

ответ

6

Это происходит потому, что вы выполняете всю обработку в Load event for the form. Это называется до, форма показана в первый раз.

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

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

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

Я переместил код для вашего метода Eat и инкапсулировал его в форму, чтобы показать вам пример использования класса BackgroundWorker, но идеальным решением было бы выставить событие, чтобы указать, когда количество пицца потребляет изменения.

Также обратите внимание, что вы должны переопределить protected Dispose method on the Form class, чтобы правильно утилизировать экземпляр BackgroundWorker, когда форма удалена.

Вот что пример выглядит следующим образом:

public void SpawnPizzaProgressBarForm(object sender, EventArgs e) 
{ 
    FormPizzaProgressBar Form = new FormPizzaProgressBar(); 
    Form.ShowDialog(); 
} 

... 

BackgroundWorker worker = new BackgroundWorker(); 

public void ProgressBarForm_Load(object sender, EventArgs e) 
{ 
    // Initialize the background worker. 
    worker = new BackgroundWorker(); 

    // Indicate that the worker supports progress. 
    worker.WorkerSupportsProgress = true; 

    // Subscribe to the DoWork event. 
    worker.DoWork += (s, e) => { 
     // Create the pizza instance. 
     Pizza = new Pizza(); 

     // Process the slices. 
     foreach (var Slice in Pizza) 
     { 
      // Clear the slice. 
      Slice.Clear(); 

      // Report the progress. 
      worker.ReportProgress(Slice.Index/Pizza.Count() * 100); 
     } 
    }; 

    // Subscribe to the ProgressChanged event. 
    worker.ProgressChanged = (s, e) => { 
     // Update the progress bar. 
     PizzaEatingProgressBar.Value = e.ProgressPercentage; 
    }; 

    // Subscribe to the RunWorkerCompleted event. 
    worker.RunWorkerCompleted = (s, e) => { 
     // Close the dislog. 
     this.Close(); 
    }; 
} 

// Must override to properly dispose of the background worker. 
protected override void Dispose(bool disposing) 
{ 
    // Call the base. 
    base.Disposing(disposing); 

    // Dispose of the background worker if disposing is true. 
    if (disposing) worker.Dispose(); 
} 
+0

+1 для определения события, я не обращал на это внимания и только что принял проблемы с окраской с блокировкой потоков пользовательского интерфейса. –

1

Это выглядит как тугая петля - вам необходимо либо разместить работу на фоне поток с помощью BackgroundWorker, или обмануть и дать UI время для обновления с помощью вызова Application.DoEvents() (обрабатывает очередь сообщений, которая включает в себя краску команд).

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

0

Вам нужно использовать потоковую передачу, чтобы обновить пользовательский интерфейс, в то время как BackgroundWorker обрабатывает ваш фактический процесс. Проконсультируйтесь с this article (от уважаемого Джона Скита) перед тем, как приступить к работе.

3

Winforms основан на API Windows, который не обновляет элементы интерфейса, если только нить, на которой были созданы элементы графического интерфейса «накачкой». WinForms вызвал ваш метод ProgressForm_Load в потоке, на котором он должен «накачать» сообщения, чтобы обновлять элементы GUI. Вы не перекачиваете очередь сообщений во время вашей операции в Eat. Итак, если элементы GUI не обновляются, вы не увидите изменения в строке выполнения.

самым простым решением является позвонить по телефону Application.DoEvents в ваш метод Eat. Лучшим ответом является длительная операция в другом потоке, отображение песочных часов во время этой операции и периодическое информирование индикатора выполнения для обновления с использованием стиля обновления GUI Invoke (вы не можете вызвать большинство методов элементов GUI непосредственно из нить, кроме потока, на котором они были созданы).

+0

Это отличный ответ, а скорее информационный пост. Спасибо. –

2
PizzaEatingProgressBar.Value = (Slice.Index/Pizza.Count())*100 

Это не работает, если Slice.Index как целое число. Чтобы получить разделение с плавающей запятой, вам нужно сделать его двойным. Например:

PizzaEatingProgressBar.Value = (int)((double)Slice.Index/Pizza.Count) * 100); 

или сделать это следующим образом:

PizzaEatingProgressBar.Value = (Slice.Index * 100)/Pizza.Count; 

что обеспечивает разделение не может усечение до 0, как исходное выражение сделал. Вопреки всем советам, ProgressBar делает, когда вы меняете свойство Value. Хотя ваше окно остается кататоническим.

+0

Спасибо! В моем случае это решит мою проблему! –

Смежные вопросы