很多時候,我開發軟件的時候 需要開啟線程到后台處理大數據,不斷更新數據庫,但又要同時修改前台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