2009-07-01 3 views
12

В моей программе [C# + winforms]. У меня есть индикатор выполнения & listview.Winforms Индикатор выполнения не обновляется (C#)

С помощью одного метода я выполняю некоторые операции &, а затем обновляю данные в Listview. Нет добавленных записей - это значение, которое я устанавливаю для свойства ProgressBar.value. То, что я хочу здесь, заключается в том, что по значению индикатора прогресса он должен показать свой прогресс. Однако индикатор выполнения не обновляется. Только в конце строки выполнения выполнения программы отображается весь прогресс, то есть 100%

Может ли кто-нибудь помочь мне в этом отношении?

Спасибо, Amit

+2

я не знаю достаточно о C# здесь, чтобы ответить, но в Java Swing он должен иметь отдельный поток, иначе вы получите такое же поведение. – Chet

ответ

26

Это звучит, как вы блокируете поток пользовательского интерфейса - т.е. вы не выпустили систему, чтобы сделать любую картину.

Хакерный ответ заключается в том, чтобы ввести код Application.DoEvents() в ваш код - но это рискованно, и у него есть проблемы с повторным подключением и т. Д .; и это просто немного хаки.

Лучшим вариантом может быть сделать обработку на BackgroundWorker, периодически переключившись на поток пользовательского интерфейса, чтобы обновить вещи (Control.Invoke) - но это может быть сложно, если вы добавляете много элементов в ListView.

Полный пример (хотя вы можете партии обновления пользовательского интерфейса - не построчно):

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows.Forms; 

class MyForm : Form 
{ 
    BackgroundWorker worker; 
    ListView list; 
    Button btn; 
    ProgressBar bar; 
    public MyForm() 
    { 
     Text = "Loader"; 
     worker = new BackgroundWorker(); 
     worker.WorkerReportsProgress = true; 
     worker.ProgressChanged += worker_ProgressChanged; 
     worker.DoWork += worker_DoWork; 
     worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
     list = new ListView(); 
     list.Dock = DockStyle.Fill; 
     Controls.Add(list); 
     btn = new Button(); 
     btn.Text = "Load"; 
     btn.Dock = DockStyle.Bottom; 
     Controls.Add(btn); 
     btn.Click += btn_Click; 
     bar = new ProgressBar(); 
     bar.Dock = DockStyle.Top; 
     Controls.Add(bar); 
    } 

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     btn.Enabled = true; 
    } 

    void btn_Click(object sender, EventArgs e) 
    { 
     worker.RunWorkerAsync(); 
     btn.Enabled = false; 
    } 


    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     for (int i = 0; i < 100; i++) 
     { 
      string newRow = "Row " + i.ToString(); 
      worker.ReportProgress(i, newRow); 
      Thread.Sleep(100); 
     } 
    } 

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     list.Items.Add((string)e.UserState); 
     bar.Value = e.ProgressPercentage; 
    } 

    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new MyForm()); 
    } 
} 
0

ProgressBar.Value должен находиться в диапазоне от 0 до 100.

Моя догадка что ваша проблема в том, что вы обновляете ListView в потоке графического интерфейса. Это означает, что вам нужно будет позвонить Application.DoEvents() после изменения свойства ProgressBar.Value.

Лучше всего запустить на BackgroundWorker и использовать событие ProgressChanged для обработки ProgressBar.

Here's another question примерно такая же тема.

+0

Почему значение индикатора выполнения должно быть от 0 до 100? – Hemant

+0

Нет никакой причины, кроме удобства при работе с процентами ... –

+0

Вы можете увеличить max max progress, установив progressBar1.Maximum = [int], где [int] является целым числом. –

3

Как сказал Марк, вы хотите убедиться, что вы откручиваете новый поток, чтобы выполнить долгое вычисление. Таким образом, поток пользовательского интерфейса (который должен делать все обновления экрана) может перерисовывать панель progres всякий раз, когда вы изменяете процент завершения.

Важно отметить, что только Пользовательский интерфейс может обновлять интерфейс. Итак, как только вы работаете в отдельном потоке, вам нужно пройти дополнительный обруч, чтобы убедиться, что изменение пользовательского интерфейса обрабатывается в потоке пользовательского интерфейса. Если вы не уверены, какой поток вы используете, вы можете проверить значение InvokeRequired (если ваш класс является System.Windows.Form), чтобы узнать, действительно ли вы в потоке пользовательского интерфейса.

Чтобы обработать вашу команду в потоке пользовательского интерфейса, используйте функцию Control.Invoke(), чтобы убедиться, что обновление обрабатывается в потоке пользовательского интерфейса для элемента управления, с которым вы работаете.

В моем примере ниже я создаю тип функции делегата и заранее объявляю вызываемую функцию .... Я не делал этого ни с одной из классных функций C# 3.5, но я уверен, вы могли бы работать выражение lamba, чтобы сделать то же самое.

private void bCreateInvoices_Click(object sender, EventArgs e) 
    { 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(CreateInvoices); 
     worker.RunWorkerAsync(this); 
    } 

// Here is the long running function that needs to update the progress bar 
public void CreateInvoices(object sernder, DoWorkEventArgs e) 
    { 
     int totalChecked = CountCheckedServiceOrders(); 
     int totalCompleted = 0; 

     foreach (...data to process...) { 
      totalCompleted++; 
      if (InvokeRequired) { 
       Invoke(new Change(OnChange), "status text", 
         totalCompleted, totalChecked);     
      } 
     } 
    } 

    // this code updates the status while a background thread works 
    private delegate void Change(string status, int complete, int total); 
    private void OnChange(string status, int complete, int total) 
    { 
     if (status == null) { 
      progressBar.Visible = false; 
      lStatus.Text = "Task complete"; 
      progressBar.Value = 0; 
     } else { 
      progressBar.Visible = true; 
      progressBar.Minimum = 0; 
      progressBar.Maximum = total; 
      progressBar.Value = complete; 
      lStatus.Text = status; 
     } 

    } 

Посмотрите на MSDN Control.InvokeRequired manual page и MSDN Control.Invoke manual page для некоторых больше информации.

4

Действительно К сожалению друзья,

На самом деле, я assiging значение поля ProgressBar.value но метод обновления использование техника его подводит(). Я использовал, что & моя проблема решена.

Спасибо всем за ваши ответы

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