Приложение перестает отвечать на запросы при добавлении тысяч строк

У меня есть приложение Windows Forms, которое создает фоновый поток для поиска в файлах и добавляет соответствующие имена файлов в DataGridView. Фоновый поток использует BeginInvoke для добавления строк в DataGridView, и все работает нормально, если фоновый поток не возвращает тысячи результатов. Пользовательский интерфейс работает отлично, даже если фоновый поток обрабатывает тысячи файлов, если только он не пытается добавить несколько тысяч строк в DataGridView.

Я попытался добавить строки одну за другой, буферизовать их и добавить 100 строк одновременно. Но интерфейс приложения перестает отвечать на запросы. Фоновый процесс работает быстрее, чем поток пользовательского интерфейса, и всегда есть новые строки для добавления в DataGridView.

Я даже попробовал Application.DoEvents (в потоке пользовательского интерфейса), но это тоже не помогло.

Есть идеи? Можно ли это исправить без добавления задержки в фоновый поток?

заранее спасибо

5 ответов

Решение

Похоже, использование Invoke вместо BeginInvoke для добавления строк является самым простым решением. Это немного замедляет фоновый поток, но не позволяет интерфейсу перестать отвечать на запросы. Поскольку вы не добавляете заранее заданную задержку в фоновый поток, я думаю, что может быть приемлемо немного замедлить фоновый поток только для того, чтобы позволить потоку пользовательского интерфейса наверстать упущенное. Использование SuspendLayout и ResumeLayout также не помогло при использовании BeginInvoke. Я еще не пробовал виртуальный режим с общими строками, но это тоже может помочь.

Убедитесь, что вы звоните SuspendLayout() а также ResumeLayout() до и после добавления всех новых строк соответственно. Без звонка SuspendLayout перед добавлением всех строк, DataGridView будет перекрашиваться после каждой добавленной строки, что немного замедлит ход событий.

Попробуйте использовать виртуализацию данных: http://msdn.microsoft.com/en-us/library/ms171622.aspx

Мне показалось, что проблема заключается в том, что полосы прокрутки перекрашиваются каждый раз, когда добавляется строка, если я добавлю, скажем, 10000 строк. Я решил эту проблему, установив полосы прокрутки в datagridview на None перед заполнением и восстановив после заполнения, например:

ScrollBars bars = this.ScrollBars; this.ScrollBars = System.Windows.Forms.ScrollBars.None;

... заполнить здесь (у меня есть переопределенный элемент управления DataGridView)

this.ScrollBars = bars;

SuspendLayout почему-то не работает в случае добавления тысяч строк.

Один из способов - создать основной поток BlockingCollection<string> это служит очередью, в которую фоновый поток может добавлять строки. Когда фоновый поток завершает добавление, он вызывает CompleteAdding,

Поток пользовательского интерфейса также создает таймер, который срабатывает с некоторой частотой (вероятно, вы определили это экспериментально). Таймер Elapsed событие проверяет, есть ли что-нибудь в очереди, и, если да, удаляет один элемент и добавляет его в DataGridView, Когда таймер Elapsed событие видит, что в очереди IsComplete свойство True, он останавливается и избавляется от таймера.

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

Другие вопросы по тегам