Сведения о вопросе

Codeliver

22:12, 17th August, 2020

Теги

Windows формы потоков и событий - ListBox обновления быстро, но progressbar испытывает огромную задержку

Просмотров: 474   Ответов: 6

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

Основной запечатанный класс '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 args содержит строковое сообщение, максимальное значение int для индикатора выполнения и текущее значение progress int. В Windows форма зарегистрировавшегося на мероприятие:

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, похоже, обновляется очень быстро ,но индикатор выполнения никогда не перемещается, пока пакет не будет почти завершен??? а что дает ?



  Сведения об ответе

9090

00:08, 25th August, 2020

Может быть, вы можете попробовать компонент BackgroundWorker. Это облегчает нарезание резьбы. Примеры здесь:


  Сведения об ответе

FAriza

07:19, 12th August, 2020

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


  Сведения об ответе

DINO

10:03, 21st August, 2020

Вы случайно не запускаете Windows Vista? Я заметил точно такую же вещь в некоторых приложениях, связанных с работой. Почему-то кажется, что есть задержка, когда индикатор выполнения "animates".


  Сведения об ответе

DINO

23:30, 29th August, 2020

@John

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

@Will

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

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

@All

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


  Сведения об ответе

9090

07:28, 19th August, 2020

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

Предложение использовать BackgroundWorker является хорошим - определенно лучше, чем пытаться кувалдой выбить свой путь из проблемы с нагрузкой вызовов обновления / обновления.

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


  Сведения об ответе

прога

02:19, 24th August, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться