Пользовательский интерфейс застрял во время обновления ProgressBar - PullRequest
1 голос
/ 25 марта 2012

Я использую DLL-библиотеки Pcapdot.net для отправки буфера пакетов на мой сетевой адаптер.Я проверил свой файл Wireshark и собрал всю информацию, например, количество пакетов, длительность и т. Д. Мой основной класс отправляет буфер и имеет несколько свойств (количество пакетов, длительность ..). В основном потоке я проверяю этот класс с помощью BackgroundWorker.ProgressChanged:

            bgWoSingle = new BackgroundWorker();
            bgWoSingle.WorkerReportsProgress = true;
bgWoSingle.ProgressChanged += new ProgressChangedEventHandler(bgW_ProgressChanged);

Каждый пакет в файле Wireshark имеет временную метку, и, конечно, я могу отправить этот буфер с другой скоростью, увеличив или уменьшив временную метку между пакетами.Теперь моя проблема:

Одно из свойств, которые я проверяю, это количество пакетов, которые я уже отправил.Поскольку я знаю, сколько пакетов содержит мой файл, я могу показать прогресс через индикатор выполнения.Если я изменяю скорость отправки на максимум, удаляя всю задержку между воспроизведением пакетов, скорость становится очень высокой, и индикатор выполнения и весь пользовательский интерфейс застряли, пока он не закончил отправку всех пакетов.Как я могу это изменить?Может быть, обновить мой ProgressBar через другой поток?

это моя функция, которая проверяет мой класс:

  void bgW_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
    //bla bla bla (check all Class properties)

        pcap = e.UserState as Pcap;
        progressBar1.Value = e.ProgressPercentage; //here is my progressBar update


    //bla bla bla (check all Class properties)
  }

Ответы [ 2 ]

7 голосов
/ 25 марта 2012

Вы просто слишком часто вызываете ReportProgress ().Так часто, что поток пользовательского интерфейса наводнен запросами вызова и больше не может выполнять свои обычные обязанности.Как рисовать и реагировать на входные события.Поскольку, когда оно будет готово выполнить следующее уведомление, будет еще один запрос для вызова обработчика события ProgressChanged, он идет первым.

Вам нужно будет замедлить его до разумного уровня.Разумный легко определить, вы делаете это только для человеческих глаз.Который не может видеть ничего, кроме размытия, когда вы делаете это быстрее, чем 20 раз в секунду.Вы проходите этот путь прямо сейчас, вероятно, за тысячу раз в секунду.Один простой способ - просто отсчитать 50 записей, прежде чем вызывать ReportProgress.Твик по необходимости.

0 голосов
/ 25 марта 2012

Я не знаю Pcapdot.net, но я знаю Winforms, поэтому я могу дать вам пару советов.

Похоже, что ваш пользовательский интерфейс застрял в том смысле, чтоокно не отвечает (вы не можете нажимать активные кнопки или редактировать текстовые поля, и при попытке окно становится серым).В этом случае у вас есть проблема с многопоточностью.Я не знаю, является ли BackgroundWorker библиотечным классом или классом, который вы создали, но вы должны быть уверены, что любая операция ввода-вывода выполняется в другом потоке.Хотя название предполагает, что это происходит, я не уверен, как вы начнете процесс против того, что предполагается API.Например, некоторые библиотеки позволяют вам вызывать метод start, который разветвляет другой поток, в то время как другие требуют, чтобы вы вызывали метод execute из потока, который вы уже разветвили.Это имеет значение.

Чтобы обновить пользовательский интерфейс из потока, не являющегося пользовательским интерфейсом, вы всегда должны использовать метод [Control.Invoke][1] (если вам нужно приостановить поток до обновления пользовательского интерфейса) или Control.BeginInvoke (еслиВы хотите продолжить как можно скорее).

Мой Lambda-fu не тренируется ежедневно, поэтому, пожалуйста, исправьте меня, если я сделаю ошибку в моем синтаксисе

progressBar1.Invoke(delegate() {progressBar1.Value = e.ProgressPercentage;});

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

Если вы запускаете этот метод progressChanged внутри try-catch, я вижу проблемы, потому что когда вы обновляете процент progressBar, вы получаете исключение, которое может быть замаскировано.Я также надеюсь, что ProcessPercentage - это целое число в диапазоне от 0 до 100, а не double в диапазоне от 0 до 1, что приводит к тому, что планка, по-видимому, не прогрессирует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...