后台線程處理數據,如何實時更新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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM