在C#中使用后台工作程序的状态列表框更新问题

时间:2019-05-28 14:22:36

标签: c# .net

我正在尝试使用后台工作程序来更新C#窗体中用于状态窗口的列表框。从MyForm类之外的另一个类调用addToStausLog()方法时,即使我将表单的实例传递给另一个调用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;
        }

1 个答案:

答案 0 :(得分:0)

Thread.Sleep在这里不是答案。您可能需要的是Application.DoEvents。这将处理Windows消息队列中当前正在等待的所有消息。

Thread.Sleep只是告诉线程进入睡眠状态(指定的毫秒数)。如果您的后台工作程序正在UI线程上运行,那么您正在使UI线程进入睡眠状态,这实际上是昏昏欲睡的。 (重要:所有Windows窗体都在UI线程上运行。)

当然,还有一些替代设计,其中涉及旋转单独的执行线程。但是这些都有其自身的问题,在盲目地走这条路之前,您应该注意它们。