2008-08-15 1 views
4

Наша команда создает новую систему документооборота для замены старой. Мне было поручено перенести старые данные в новую схему. Я решил сделать это, создав небольшой проект Windows Forms, поскольку схема радикально отличается и прямые скрипты TSQL не являются адекватным решением.Windows Threads Threading и Events - ListBox быстро обновляется, но progressbar испытывает огромную задержку

Основной запечатанный класс «ImportController», что делает работу заявляет следующее событие делегата:

public delegate void ImportProgressEventHandler(object sender, ImportProgressEventArgs e); 
public static event ImportProgressEventHandler importProgressEvent; 

Главное окно начинает статический метод в этом классе, используя новую тему:

Thread dataProcessingThread = new Thread(new ParameterizedThreadStart(ImportController.ImportData)); 
dataProcessingThread.Name = "Data Importer: Data Processing Thread"; 
dataProcessingThread.Start(settings); 

Аргументы ImportProgressEvent содержат строковое сообщение, максимальное значение int для индикатора выполнения и текущее значение текущей реализации. Форм-subcribes окна к событию:

ImportController.importProgressEvent += new ImportController.ImportProgressEventHandler(ImportController_importProgressEvent); 

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

private delegate void TaskCompletedUIDelegate(string completedTask, int currentProgress, int progressMax); 

private void ImportController_importProgressEvent(object sender, ImportProgressEventArgs e) 
      { 
       this.Invoke(new TaskCompletedUIDelegate(this.DisplayCompletedTask), e.CompletedTask, e.CurrentProgress, e.ProgressMax); 
      } 

Наконец прогресс бар и ListBox обновляется:

private void DisplayCompletedTask(string completedTask, int currentProgress, int progressMax) 
     { 
      string[] items = completedTask.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 

      foreach (string item in items) 
      { 
       this.lstTasks.Items.Add(item); 
      } 

      if (currentProgress >= 0 && progressMax > 0 && currentProgress <= progressMax) 
      { 
       this.ImportProgressBar.Maximum = progressMax; 
       this.ImportProgressBar.Value = currentProgress; 
      } 
     } 

Дело в том, что ListBox, кажется, обновляется очень быстро, но индикатор прогресса никогда не перемещается, пока партия почти не завершена? что дает ?

ответ

0

@John

Спасибо за ссылки.

@Will

Там нет никакой выгоды от threadpooling, как я знаю, что это будет только когда икру один поток. Использование потока - это чисто реагирующий пользовательский интерфейс, в то время как SQL Server подвергается чтению и записи. Это, конечно, не короткая жизнь.

Что касается кувалды, вы правы. Но, как оказалось, моя проблема была между экраном и стулом в конце концов. Кажется, у меня есть неспособная партия данных, у которой есть много гораздо больше записей иностранных ключей, чем другие партии, и просто происходит, чтобы получить выбранный в начале процесса, то есть currentProgress не получает ++ 'd в течение 10 секунд.

@ Все

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

-1

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

Рекомендация использования BackgroundWorker - это хороший вариант - определенно превосходящий попытку кувалды, избавиться от проблемы с загрузкой вызовов Refresh/Update.

И BackgroundWorker будет использовать поток пула, который является более дружелюбным способом поведения, чем создание собственной короткоживущей нити.

0

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

0

Вы случайно запускаете Windows Vista? Я заметил то же самое в некоторых связанных с работой приложениях. Так или иначе, кажется, что существует задержка, когда индикатор прогресса «оживляет».

-1

Там нет никакой выгоды от threadpooling, как я знаю, что это будет только когда нерест один нити. Использование потока - это чисто , чтобы иметь отзывчивый пользовательский интерфейс, в то время как SQL Сервер обрабатывается с чтением и пишет. Это, конечно, не короткая живая нить.

ОК, я ценю это и рад, что вы нашли свою ошибку, но посмотрели ли вы на BackgroundWorker? Это делает практически то, что вы делаете, но стандартизированным способом (т. Е. Без ваших собственных делегатов) и без необходимости создавать новый поток - оба из которых (возможно, небольшие, но, возможно, еще полезные).

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