A. C#多線程與UI響應 跨線程更新UI
lblStatus.Text = "執行中,請稍候……"; Func<int> longTask = new Func<int>(delegate(){ // 模擬長時間任務 Thread.Sleep(2000); // 返回任務結果:5 return 5;});// 發起一次非同步調用,實際上就是在.net線程池中執行longTask// 這時由於是其它線程在工作,UI線程未被阻塞,所以窗體不會假死longTask.BeginInvoke(ar =>{ // 使用EndInvoke獲取到任務結果(5) int result = longTask.EndInvoke(ar); // 使用Control.Invoke方法將5顯示到一個label上,如果沒有Invoke, // 直接寫lblStatus.Text="5",將會拋出跨線程訪問UI控制項的異常 Invoke(new Action(() => lblStatus.Text = "執行結果是:" + result));}, null);
B. 如何實時更新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();
}
}
}
C. java多線程更新資料庫批量的數據信息嗎怎麼實現
//將資料庫中的數據條數分段
public void division(){
//獲取要導入的總的數據條數
String sql3="SELECT count(*) FROM [CMD].[dbo].[my1]";
try {
pss=cons.prepareStatement(sql3);
rss=pss.executeQuery();
while(rss.next()){
System.out.println("總記錄條數:"+rss.getInt(1));
sum=rss.getInt(1);
}
//每30000條記錄作為一個分割點
if(sum>=30000){
n=sum/30000;
resie=sum%30000;
}else{
resie=sum;
}
System.out.println(n+" "+resie);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
線程類
public MyThread(int start,int end) {
this.end=end;
this.start=start;
System.out.println("處理掉余數");
try {
System.out.println("--------"+Thread.currentThread().getName()+"------------");
Class.forName(SQLSERVERDRIVER);
System.out.println("載入sqlserver驅動...");
cons = DriverManager.getConnection(CONTENTS,UNS,UPS);
stas = cons.createStatement();
System.out.println("連接SQLServer資料庫成功!!");
System.out.println("載入mysql驅動.....");
Class.forName(MYSQLDRIVER);
con = DriverManager.getConnection(CONTENT,UN,UP);
sta = con.createStatement();
// 關閉事務自動提交
con.setAutoCommit(false);
System.out.println("連接mysql資料庫成功!!");
} catch (Exception e) {
e.printStackTrace();
}
// TODO Auto-generated constructor stub
}
public ArrayList<Member> getAll(){
Member member;
String sql1="select * from (select row_number() over (order by pmcode) as rowNum,*" +
" from [CMD].[dbo].[my1]) as t where rowNum between "+start+" and "+end;
try {
System.out.println("正在獲取數據...");
allmembers=new ArrayList();
rss=stas.executeQuery(sql1);
while(rss.next()){
member=new Member();
member.setAddress1(rss.getString("address1"));
member.setBnpoints(rss.getString("bnpoints"));
member.setDbno(rss.getString("dbno"));
member.setExpiry(rss.getString("expiry"));
member.setHispoints(rss.getString("hispoints"));
member.setKypoints(rss.getString("kypoints"));
member.setLevels(rss.getString("levels"));
member.setNames(rss.getString("names"));
member.setPmcode(rss.getString("pmcode"));
member.setRemark(rss.getString("remark"));
member.setSex(rss.getString("sex"));
member.setTelephone(rss.getString("telephone"));
member.setWxno(rss.getString("wxno"));
member.setPmdate(rss.getString("pmdate"));
allmembers.add(member);
// System.out.println(member.getNames());
}
System.out.println("成功獲取sqlserver資料庫數據!");
return allmembers;
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("獲取sqlserver資料庫數據發送異常!");
e.printStackTrace();
}
try {
rss.close();
stas.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void inputAll(ArrayList<Member> allmembers){
System.out.println("開始向mysql中寫入");
String sql2="insert into test.my2 values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try {
ps=con.prepareStatement(sql2);
System.out.println("-------------------------等待寫入數據條數: "+allmembers.size());
for(int i=0;i<allmembers.size();i++){
ps.setString(1, allmembers.get(i).getPmcode());
ps.setString(2, allmembers.get(i).getNames());
//System.out.println(allmembers.get(i).getNames());
ps.setString(3, allmembers.get(i).getSex());
ps.setString(4, allmembers.get(i).getTelephone());
ps.setString(5, allmembers.get(i).getAddress1());
ps.setString(6, allmembers.get(i).getPmdate());
ps.setString(7, allmembers.get(i).getExpiry());
ps.setString(8, allmembers.get(i).getLevels());
ps.setString(9, allmembers.get(i).getDbno());
ps.setString(10, allmembers.get(i).getHispoints());
ps.setString(11, allmembers.get(i).getBnpoints());
ps.setString(12, allmembers.get(i).getKypoints());
ps.setString(13, allmembers.get(i).getWxno());
ps.setString(14, allmembers.get(i).getRemark());
//插入命令列表
//ps.addBatch();
ps.executeUpdate();
}
//ps.executeBatch();
con.commit();
ps.close();
con.close();
this.flag=false;
System.out.println(Thread.currentThread().getName()+"--->OK");
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("向mysql中更新數據時發生異常!");
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true&&flag){
this.inputAll(getAll());
}
}