Индикатор прогресса WPF не показывает правильный прогресс - PullRequest
4 голосов
/ 23 апреля 2011

У меня есть приложение, в которое я загружаю файл блоками. Мой интерфейс - WPF, и у меня есть индикатор выполнения, показывающий ход загрузки файла (загрузка выполняется отдельным потоком, а индикатор выполнения находится в отдельной форме, вызываемой дочерним потоком при запуске загрузки).

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

Теперь для каждого загруженного блока я увеличиваю значение индикатора выполнения на 1.

Но, к моему удивлению, индикатор выполнения начинает увеличиваться, но никогда не завершается (он перестает отображать прогресс после нескольких блоков).

Вот код ветки, отвечающей за загрузку файлов:

 System.Threading.Thread thread = new Thread(
   new ThreadStart(
         delegate()
         {
              // show progress bar - Progress is the name of window containing progress bar
              Progress win = new Progress();
              win.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
              win.Show();

              // find number of blocks
             long BlockSize = 4096;
             FileInfo fileInf = new FileInfo(filename);
             long FileSize = fileInf.Length;
             long NumBlocks = FileSize / BlockSize;

             //set the min and max for progress bar
             win.Dispatcher.Invoke(
                  new Action(
                     delegate()
                     {
                            win.progressBar1.Minimum = 0;
                            win.progressBar1.Maximum = NumBlocks;                                                        
                     }
             ), System.Windows.Threading.DispatcherPriority.Render);

             //upload file
             while (true)
             {

                      // code to upload the file

                      win.Dispatcher.Invoke(
                          new Action(
                              delegate()
                              {
                                 win.progressBar1.Value += 1;
                              }
                      ), System.Windows.Threading.DispatcherPriority.Render);

             }
       }

Может кто-нибудь помочь мне проанализировать, почему это происходит.

Спасибо.

1 Ответ

6 голосов
/ 23 апреля 2011

Вот проблема:

загрузка осуществляется отдельной веткой, и индикатор выполнения находится в отдельной форме вызывается дочерним потоком, когда загрузка начинается

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

Лучше всего создать форму индикатора выполнения в потоке main .

Ваш рабочий поток может затем обновить статус, а ваш основной поток обновит отображение.

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

var dispatcher = progressBar.Dispatcher;
dispatcher.BeginInvoke(new Action( () => { progressBar.Value = currentProgress }));

<ч /> Изменить после просмотра кода

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

<ч />
Progress win = new Progress();
win.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
win.Show();
System.Threading.Thread thread = new Thread(
   new ThreadStart(
         delegate()
         {
 // ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...