2016-08-09 3 views
0

У меня есть рабочий фонарик с длительной работой. Задача проходит через список файлов, и я хочу обновить пользователя, с каким файлом мы находимся. У меня есть полоска инструмента с надписью panel1.text. Индикатор выполнения работает, однако метка не изменяется в моем методе ProgressChanged, то есть он должен сказать, что обработчик File1 затем изменится на Обработку File2, но он остается на умолчанию по умолчанию.Progress Bar с ярлыком - не удалось обновить ярлык в ProgressChanged

private void btnProcess_Click(object sender, EventArgs e) 
    { 
     toolStripProgressBar1.Visible = true; 
     toolStripProgressBar1.Maximum = 1000000000; 
     panel1.Text = "Processing "; // this appears properly 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(processFiles); 
     worker.ProgressChanged += ProgressChanged; 
     worker.RunWorkerAsync(); 
     while (worker.IsBusy) 
     { 
      // the reason for this is because nothing can happen until the processing is done 
      toolStripProgressBar1.Increment(1); 
     } 
     // more processing 
    } 

    private void ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     panel1.Text = "Processing "+ e.UserState.ToString(); <<<---- This is Not Updating panel1.Text but it evaluates properly 
    } 

    private void processFiles(object sender, EventArgs e) 
    { 
     int retVal = 0; 
     foreach (string fileName in listBox1.Items) 
     { 
      ProgressChangedEventArgs ea = new ProgressChangedEventArgs(1,fileName); 
      ProgressChanged(this, ea); 

      // do more processing 

     } 
    } 

Я был бы признателен за любую помощь.

+1

Что вы подразумеваете под обновлением? текст ярлыка не меняется или что? – Rahul

+2

Цикл 'while (worker.IsBusy)' в основном не позволяет вашему потоку пользовательского интерфейса обрабатывать сообщения с краской (и не только). –

+0

Да - текст ярлыка не меняется. Похоже, я должен обновить метку в цикле. – Missy

ответ

1

Вы используете один и тот же поток, который блокируется другим процессом. Вам нужно использовать задачу для создания нового потока и, возможно, использовать Dispatcher.BeginIvoke, если элемент управления находится в другом потоке. Убедитесь, что любой щелчок кнопки и т. Д. Отмечен ключевым словом Async, чтобы сделать его асинхронным.

Пример:

Await Task mytask = Task.Run(() => 
          for(var i = 0; i < 1000; i++) 
          { 
           Label.Dispatcher.BeginInvoke(() => 
                   UpdateMe(int i, LabelClass/Component class/component)}); 

Затем внутри класса этикетки или там, где метка:

Public void UpdateMe(int i, LabelClass class) 
{ 
    class.label.content = Cint((i/Total)*100); 
    Thread.Sleep(500); 
} 

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

Если вы действительно хотите получить визуальное понимание вызова:

`Console.WriteLine($"Current Thread ID: System.Threading.Thread.CurrentThread.ManagedThreadId}");` 

Право, прежде чем идти в Task --- это даст вам основной идентификатор потока Затем внутри задачи называют его снова .. . Это даст вам идентификатор вторичного потока.
Тогда Непосредственно перед диспетчерским вызовом:

Console.WriteLine($"Do I have access to the label on this thread? {Label.Dispatcher.CheckAccess()}"; 

Если у вас есть доступ к нему будет отображаться Правда, если не будет отображаться Ложными ... В вашем случае это будет отображаться ложным, потому что его принадлежат другому потоку, но вы можете использовать Диспетчер, чтобы иметь возможность выполнять работу над этим потоком в то время как в другом потоке ...

Кроме того, я рекомендую не использовать Фоновый Работник и вместо этого использовать Задачи ... это объясняет, почему в глубине ... в основном Задачи делают все, что делают фоновые работники, и имеют больше проблем и легче работать с ...

http://blog.stephencleary.com/2013/09/taskrun-vs-backgroundworker-conclusion.html

+0

Спасибо за эту замечательную статью, Мэтт – Missy

1

Как уже прокомментировал Иван, удалите цикл while while (worker.IsBusy), поскольку он блокирует поток пользовательского интерфейса для дальнейшей обработки. Кроме того, вы должны позволить WorkerReportsProgress к true

worker.WorkerReportsProgress = true; 
    worker.ProgressChanged += ProgressChanged; 
    while (!worker.IsBusy) 
    { 
     worker.RunWorkerAsync(); 
    } 

За свой комментарий, переместить эти последующую обработку в BackgroundWorker.RunWorkerCompleted Event

+0

Позвольте мне попробовать. – Missy

+0

@ Missy, см. Редактирование в ответ, если вы хотите иметь продолжение, то подумайте над использованием TPL. – Rahul

+0

Хорошее представление о полном событии – Missy