2012-03-25 2 views
2

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

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

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

Одним из свойств, которые я проверяю, является то, сколько пакетов я уже отправил. Поскольку я знаю, сколько пакетов содержит мой файл, я могу показать прогресс через индикатор выполнения. Если я изменяю скорость отправки до максимума, удаляя всю задержку между воспроизведением пакетов, скорость будет такой же быстрой, и индикатор выполнения и весь пользовательский интерфейс застряли, пока он не закончит отправку всех пакетов. Как я могу его изменить? Может быть, обновить мой 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) 
    } 
+0

«Застрял», значит, не реагирует (т. Е. Окно становится серым при щелчке, следовательно, вы ДОЛЖНЫ выполнять ввод-вывод из другого потока) или просто не обновляется индикатор выполнения? –

+0

Да, он стал серым на клике с сообщением «не отвечающий» до его завершения, как я могу обновить все мои bgW_ProgressChanged через другой поток? – falukky

ответ

1

Я не знаю Pcapdot.net, но я знаю Winforms, так что я могу дать вам несколько советов.

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

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

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

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

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

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

+0

Я только что прочитал ваш комментарий, пожалуйста, проигнорируйте вторую часть моего вопроса –

+0

извините за вопрос, но я не понял, что я должен делать, что лучший способ обновить мой интерфейс? – falukky

+0

Вызов метода вызова с лямбдой. Пример за несколько секунд –

6

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

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

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