从另一个线程填写列表框

时间:2017-12-12 11:03:41

标签: c# multithreading winforms

我现在正在寻找这个问题好几个小时,但却无法找到合适的解决方案。我是初学者。

我有一个带有ListBox的winforms应用程序和一个可以完成某些工作的类,它应该永远在不同的线程上运行。我希望每次在 WorkerClass.Work 中创建 MyDataStruct 到ListBox。

稍后,几个 WorkerClass 实例应该同时运行,我将使用combobox来选择要提供给ListBox的实例数据。最好让WorkerClas只返回单个MyDataStruct并将其队列保存在 Form1 类中,或者在每个 WorkerClass 中有一个队列,并用 Form1 每次变化?

是我的无效QueueToLb将队列数据添加到ListBox的好方法吗?

感谢您的支持。

    public partial class Form1 : Form
    {
        Queue<MyDataStruct> qList;
        MyDataStruct myDataStruct;
        private void RunTask()
        {
            //how do I make MyLongTask to update either qList or myDataStuct
            Task.Run(() =>
            {
                MyLongTask(0, 1000);
            });
        }
        private void MyLongTask(int low, int high)
        {
            WorkerClass wc = new WorkerClass();
            wc.Work(low,high);           
        }
        private void QueueToLb()
        {
            //is this good way to update listbox from queue?
            List<MyDataStruct> lstMds = qList.Reverse<MyDataStruct>().ToList<MyDataStruct>();
            List<string> lstStr = new List<string>();
            foreach (MyDataStruct m in lstMds)
            {
                lstStr.Add(m.ToString());
            }
            listBox1.DataSource = lstStr;            
        }
    }

    public class WorkerClass
    {
        Queue<MyDataStruct> qList; //not sure if its better to keep the queue here or in Form1
        public WorkerClass()
        {
            qList = new Queue<MyDataStruct>();
        }
        public void Work(int low, int high) //does some work forever
        {
            while (true)
            {
                if (qList.Count > 11) qList.Dequeue();
                MyDataStruct mds = new MyDataStruct();
                Random random = new Random();
                mds.dt = DateTime.Now;
                mds.num = random.Next(low, high);
                qList.Enqueue(mds);
                Thread.Sleep(1000);
            }
        }
    }

    public class MyDataStruct
    {
        public DateTime dt;
        public int num;
        public override string ToString()
        {
            StringBuilder s = new StringBuilder();
            s.Append(num.ToString());
            s.Append(" - ");
            s.Append(dt.ToShortDateString());
            return s.ToString();
        }

    }

好吧我想我已经想到了如何在这上面使用BackgroundWorker,如果有人能够验证它是否正确,我会很高兴

    public partial class Form1 : Form
    {
        Queue<MyDataStruct> qList;        
        BackgroundWorker bw = new BackgroundWorker();

        public Form1()
        {
            InitializeComponent();

            bw.WorkerReportsProgress = true;            
            bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);                        
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            qList = new Queue<MyDataStruct>(12);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            bw.RunWorkerAsync();
        }

        private void MyLongTask(int low = 0, int high = 1000)
        {
            WorkerClass wc = new WorkerClass(bw);
            wc.Work(low,high);           
        }

        private void BindToLbWithQueue()
        {            

            MyDataStruct mds = new MyDataStruct();
            Random random = new Random();
            mds.dt = DateTime.Now;
            mds.num = random.Next(0, 1000);

            qList.Enqueue(mds);
            QueueToLb();
        }

        private void QueueToLb()
        {
            //is this good way to update listbox from queue?
            List<MyDataStruct> lstMds = qList.Reverse<MyDataStruct>().ToList<MyDataStruct>();
            List<string> lstStr = new List<string>();
            foreach (MyDataStruct m in lstMds)
            {
                lstStr.Add(m.ToString());
            }
            listBox1.DataSource = lstStr;                        
        }

        #region worker
        private void Bw_DoWork(object sender, DoWorkEventArgs e)
        {
            MyLongTask();
        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            qList = (Queue<MyDataStruct>)e.UserState;
            QueueToLb();
        }
        #endregion

    }

    public class WorkerClass
    {
        Queue<MyDataStruct> qList; //not sure if its better to keep the queue here or in Form1
        BackgroundWorker bw = null;
        public WorkerClass(BackgroundWorker bw)
        {
            this.bw = bw;
            qList = new Queue<MyDataStruct>();
        }

        public void Work(int low, int high) //does some work forever
        {
            while (true)
            {
                if (qList.Count > 11) qList.Dequeue();
                MyDataStruct mds = new MyDataStruct();
                Random random = new Random();
                mds.dt = DateTime.Now;
                mds.num = random.Next(low, high);
                qList.Enqueue(mds);
                bw.ReportProgress(0, qList);
                Thread.Sleep(1000);
            }
        }
    }

    public class MyDataStruct
    {
        public DateTime dt;
        public int num;
        public override string ToString()
        {
            StringBuilder s = new StringBuilder();
            s.Append(num.ToString());
            s.Append(" - ");
            s.Append(dt.ToShortDateString());
            return s.ToString();
        }

    }

0 个答案:

没有答案