Form.Show () периодически показывает форму в потоке - PullRequest
1 голос
/ 23 декабря 2010

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

           //some code
           ...
           ...
           ...
           bool done = false;

            //Show progress in a separate thread. 
            System.Threading.ThreadPool.QueueUserWorkItem((x) =>
            {
                using (var progressDialog = new ProgressDialog())
                {
                    progressDialog.TopMost = true;
                    progressDialog.Show();

                    while (!done)
                    {
                        if(progressDialog.Message != this.strProgressMsg)
                            progressDialog.Message = this.strProgressMsg;

                        Application.DoEvents();
                    }

                    progressDialog.Close();
                }
            });

           ....
           ....
           done = true;
           ....
           ....

Проблема: Диалоговое окно Progressbar появляется несколько раз, а иногда нет. Моя функция открытия файла запускается в основном потоке. Может кто-нибудь указать мне правильное обнаружение, почему это может происходить?

Ответы [ 2 ]

5 голосов
/ 23 декабря 2010

У вас есть это задом наперед.Вот как это должно работать:

  1. Раскрутите поток, чтобы открыть файл, и попросите его перезвонить основному потоку, используя progressDialog.Invoke(), чтобы выполнить обновления GUI.(Он не должен устанавливать strProgressMsg и ждать, пока что-то еще заметит изменение - пусть он отправит обновление прямо в диалоговое окно.)
  2. Отображение диалогового окна хода выполнения модально из основного потока.1009 *

    Так что-то вроде этого:

    using (var progressDialog = new ProgressDialog()) {
        progressDialog.TopMost = true;
    
        System.Threading.ThreadPool.QueueUserWorkItem((x) =>
        {
            try {
                // this represents whatever loop you use to load the file
                while (...) {
                    // do some work loading the file
    
                    // update the status
                    progressDialog.Invoke(new MethodInvoker(
                        () => progressDialog.Message = "Hello, World!"));
                }
            } finally {
                // done working
                progressDialog.Invoke(new MethodInvoker(progressDialog.Close));
            }
        });
    
        // this will block until the thread closes the dialog
        progressDialog.ShowDialog();
    }
    
1 голос
/ 23 декабря 2010

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

  • Создайте progressDialog в потоке пользовательского интерфейса и отправьте ему сообщения через Control.Invoke, чтобы обновить его новой информацией о ходе выполнения.
  • Создайте progressDialog в потоке пользовательского интерфейса и запросите у него переменную, используя System.Windows.Forms.Timer для получения новой информации о прогрессе, которую публикует рабочий поток.

В этом случае метод опроса предпочтительнее метода Control.Invoke, потому что:

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