很多时候,我开发软件的时候 需要开启线程到后台处理大数据,不断更新数据库,但又要同时修改前台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(); } }}
下面贴出源码: