后台线程处理数据,如何实时更新UI(datagridview)多线程同步问题

很多时候,我开发软件的时候 需要开启线程到后台处理大数据,不断更新数据库,但又要同时修改前台UI,比如迅雷的下载任务,开多个线程去下载,显示层UI也要同时体现给用户知道,显示当前用户下载进度等,这样必须用到多线程,但是C#中多线程处理问题涉及到一个“界面控件不能跨线程”,因为微软认为这样会导致线程不安全问题,那么我们一般怎么处理这样的问题,既要处理数据,又要实时显示

看设计界面

数据库用到的是sqlite 英文sqlite是多线程的 但同一时间只能一个线程操作数据库,

所以要用到线程同步问题

我用LOCK进行线程同步处理

                lock (ModifStatic.o)
                {
                    queue = queueBLL.GetModel(i);
                    queueNew = queue;
                    queueNew.remainNum++;
                    queueBLL.Update(queueNew);
                }

这里又一点要注意

因为lock 里面的对象必须是一个对象,而且是全局 的 所以我吧它放到一个静态类里面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test.BLL
{
    public static class ModifStatic
    {
        private static int id = 1;

        public static int Id
        {
            get { return ModifStatic.id; }
            set { ModifStatic.id = value; }
        }

        public static object o = new object();
    }
}

这个静态类还有一个 就是记录当前是修改哪一个id的数据的

这样我们就可以只针对某个row进行修改 而不是全部整个datagridview修改,否则就显得很卡

用户会感觉界面一闪一闪的

这个程序是模拟的

写一个类来专门处理修改数据库的 开一个线程用来处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test.BLL
{
    [Serializable]
    public class ChangeDB
    {
        int i = 0;
        Random r = new Random();
        Test.Model.queue queue = null;
        Test.Model.queue queueNew = null;
        Test.BLL.queue queueBLL = new Test.BLL.queue();

        public void DBAdd()
        {
            while (true)
            {
                i = r.Next(1,8);
                lock (ModifStatic.o)
                {
                    queue = queueBLL.GetModel(i);
                    queueNew = queue;
                    queueNew.remainNum++;
                    queueBLL.Update(queueNew);
                }
                ModifStatic.Id = i;
                System.Threading.Thread.Sleep(5000);
            }
            
        }
    }
}

主页面UI

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    [Serializable]
    public partial class FormMain : Form
    {
        Test.Model.queue queue = null;
        Test.BLL.queue queueBLL = new Test.BLL.queue();
        Test.BLL.ChangeDB changeDbBLL = new Test.BLL.ChangeDB();

        private delegate void myDelegate(int id);//定义委托

        //初始化UI
        public FormMain()
        {
            InitializeComponent();
            this.dataGridView1.DataSource = queueBLL.GetAllList();
            this.dataGridView1.DataMember = "ds";
        }

        //启动更新线程
        Thread myThread;
        private void FormMain_Load(object sender, EventArgs e)
        {
            myThread = new Thread(startFillDv);//实例化线程
            myThread.IsBackground = true;
            myThread.Start();
        }

        //不断更新UI
        private void startFillDv()
        {
            while (true)
            {
                lock (Test.BLL.ModifStatic.o)
                {
                    Grid(Test.BLL.ModifStatic.Id);  
                }
                Thread.Sleep(3000);//更新频率为3秒
            }

        }

        //更新UI
        private  void Grid(int id)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDelegate(Grid), new object[] { id });
            }
            else
            {
                try
                {
                    //修改改id对应的行
                    for (int i = 0; i < this.dataGridView1.Rows.Count; i++)
                    {
                        if (Convert.ToInt32(this.dataGridView1.Rows[i].Cells[0].Value) == id)
                        {
                            queue = queueBLL.GetModel(id);
                            this.dataGridView1.Rows[i].Cells[1].Value = queue.remainNum;
                        }
                    }
                }
                catch
                {

                }
            }
        }

        //结束线程
        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (this.myThread.IsAlive)
            {
                this.myThread.Abort();
            }
        }

        //修改数据库
        Thread th = null;
        private void buttonModif_Click(object sender, EventArgs e)
        {
            th = new Thread(new ThreadStart(changeDbBLL.DBAdd));
            th.IsBackground = true;
            th.Start();
        }
    }

}

下面贴出源码:
http://www.kuaipan.cn/file/id_42714965882189276.htm

原文地址:https://www.cnblogs.com/maijin/p/2830191.html