Проблема с обновлением списка состояний с использованием фонового рабочего процесса в С#

Я пытаюсь использовать фонового работника для обновления списка, используемого для окна состояния в моей форме на С#. Похоже, он не работает должным образом, когда метод addToStatusLog() вызывается из другого класса вне класса MyForm, даже если я передаю экземпляр формы другому классу, который вызывает элемент обновления addToStatusLog. Вместо этого обновление не происходит до тех пор, пока член класса не завершит свою работу и не вернется обратно в класс MyForm. Возможно, есть лучший подход к созданию окон состояния в реальном времени, которые будут запускаться из любого класса, в который передается MyForm. Я новичок в рабочих потоках, поэтому может кто-нибудь просмотреть и сообщить мне, что я могу делать неправильно или что можно улучшить.

        public MyForm()
        {
            InitializeComponent();

            // Setup background task to update listbox status so UI is unaffected
            _lListBoxQue = new List<string>();
            bw_listBoxBGWorker = new BackgroundWorker();
            bw_listBoxBGWorker.DoWork += (o, args) => LstbxThread_doWork();
            bw_listBoxBGWorker.RunWorkerCompleted += (o, args) => LstbxThread_completed();
        }

        private void LstbxThread_doWork()
        {
            System.Threading.Thread.Sleep(100);
        }

        private void LstbxThread_completed()
        {
            // Update listbox
            lstStatusBox.BeginUpdate();
            lstStatusBox.Items.Clear(); // clear entries
            lstStatusBox.Items.AddRange(_lListBoxQue.ToArray());
            lstStatusBox.EndUpdate();
        }

        public String addToStatusLog(String sMsg)
        {
            _lListBoxQue.Add(sMsg);
            if (_lListBoxQue.Count > _iStatusLogMaxLines)    // > max?
                _lListBoxQue.RemoveAt(0); // remove top element?

            if ( !bw_listBoxBGWorker.IsBusy )    // background not busy?    
                bw_listBoxBGWorker.RunWorkerAsync();    // update listbox in back ground task           
            System.Threading.Thread.Sleep(100);
            return sMsg;
        }

Это член, который вызывает другой класс, который несколько раз пытается вызвать addToStatusLog во время процесса, но обновления списка не происходят до тех пор, пока MyClass(this).updateDB() не завершится. Мне нужно видеть обновления в реальном времени, когда работает функция updateDB(). Должен быть способ заставить это работать, я надеюсь...

        private void btnUpdateDB_Click(object sender, EventArgs e)
        {
        if (_bIsUpdateEventRunning == false ) // is event not busy?
        {
            _bIsUpdateEventRunning = true;
            new MyClass(this).updateDB();
            _bIsUpdateEventRunning = false;
        }

        }

Пример класса, вызываемого для обновления списка формы.

    Public class MyClass{

            private MyForm _pForm;

            public MyClass(MyForm pForm){ _pForm= pForm; }

            public void updateDB(){ 
                _pForm.addToStatusLog("Hello World");
            }

    }

Обновленный фикс без фонового рабочего:

        public String addToStatusLog(String sMsg)
        {
            _lListBoxQue.Add(sMsg);
            if (_lListBoxQue.Count > _iStatusLogMaxLines)    // > max?
                _lListBoxQue.RemoveAt(0); // remove top element?

            lstStatusBox.BeginUpdate();
            lstStatusBox.Items.Clear(); // clear entries
            lstStatusBox.Items.AddRange(_lListBoxQue.ToArray());
            lstStatusBox.EndUpdate();
            Application.DoEvents();

            return sMsg;
        }

Почему ваш DoWork не работает? Разве нам не нужно видеть метод updateDB(), который вы вызываете, если этот код не работает?

LarsTech 28.05.2019 16:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Thread.Sleep здесь не ответ. Скорее всего, вам понадобится Application.DoEvents. Это обрабатывает все сообщения, ожидающие в настоящее время в очереди сообщений Windows.

Thread.Sleep просто говорит потоку перейти в спящий режим на указанное вами количество миллисекунд. Если ваш фоновый рабочий процесс работает в потоке пользовательского интерфейса, вы переводите поток пользовательского интерфейса в спящий режим, и он фактически находится в коматозном состоянии. (Важный: все формы Windows выполняются в потоке пользовательского интерфейса.)

Существуют, конечно, и альтернативные конструкции, в которых задействованы отдельные потоки выполнения. Но у них есть свои проблемы, и вы должны помнить о них, прежде чем слепо идти по этому пути.

Согласитесь, я полностью исключил фоновый рабочий поток для этой задачи и добавил Application.DoEvents после загрузки списка, и это работает отлично. Tnx.

user7071176 28.05.2019 23:20

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