for (int a = 0; a < dts.Rows.Count; a++) { DataRow row = dts.Rows[a]; trd = new Thread(new ParameterizedThreadStart(ResultOut)); trd.IsBackground = true; trd.Start(row); if (trd.ThreadState == System.Threading.ThreadState.Aborted || trd.ThreadState == System.Threading.ThreadState.Stopped) { trd.IsBackground = true; trd.Start(dts.Rows[a]); } }
public void ResultOut(object row) { DataRow r = (DataRow)row; { if (!lvDataInDBInfo.InvokeRequired) { try { AreaCode = r["AreaCode"].ToString(); string server = r["SSIPAddess"].ToString(); string uid = r["SSLoginName"].ToString(); string pwd = r["SSLoginPwd"].ToString(); SStationName = r["SStationName"].ToString(); sqlconn = "server=" + server + ";database=EnvDataCity;uid=" + uid + ";pwd=" + pwd; for (int i = 1; i <= 1; i++) { //if (AreaCode != "SS4301") { queryDate = Convert.ToDateTime(DateTime.Now.AddDays(-i).ToString("yyyy-MM-dd")); try { ZdHours(AreaCode, sqlconn); { dsDailyRpt = DbaseCS.ExecuteDataSet("up_GetNewDailyRpt", new SqlParameter[] { new SqlParameter("@queryDate", queryDate), new SqlParameter("@areaCode", AreaCode) }, CmdType.StoreProcedure); if (dsDailyRpt.Tables[0].Rows.Count > 0) { dsDailyRpt.Tables[0].Rows.Clear(); } NewRptUtil.GetDailyRptViewTable(dsDailyRpt, SStationName, AreaCode.Substring(2, 4) + "00", ref dsValues, queryDate); SaveDataToCity(); r["IsUpdated"] = true; // SaveDataToProvince(); // AduitNewHourReport(); } } catch (Exception ex) { // lvDataInDBInfo.Items.Add("数据自动入库失败"); } } } } catch (Exception ex) { lvDataInDBInfo.Items.Add(ex.Message); } } else { Synchronization tmpDel = new Synchronization(ResultOut); this.Invoke(tmpDel, row); } } }
上面的DataTable就是图上的dts.感觉没有多线程的效果。并且还掉数据。怎么完整的实现多线程,循环每个地区城市???
你最后大量的操作都丢到ui线程上去了
if (!lvDataInDBInfo.InvokeRequired) {....
这里是ui线程在处理中,所以你的感觉很正确。
抛开你的问题,你的代码实现有相当多的问题。
1.在循环中依次去操作db这个基本是不可取的,数据量大了你这玩意就算实现的是正确的估计也没办法用
2.你线程使用的姿势不对,完全无法看懂
if (trd.ThreadState == System.Threading.ThreadState.Aborted || trd.ThreadState == System.Threading.ThreadState.Stopped)
这个判断到底要干嘛
针对这种场景一般都是用线程池,否则就算你线程足够你这样跑光线程切换就是要死人的
是的,循环连接每个城市去取数据,进行处理。数据量有点大。肯定要使用多线程。但是多线程以前没有涉及到过。具体怎么使用,能给个详细的参考吗?
@转角VV: 你用的framework版本多少?
@Daniel Cai: 4.0。
@转角VV: 一般针对你这种场景就直接用线程池了。
for(int i=0;i<100;i++)
{
var target=i;
ThreadPool.QueueUserWorkItem(_=>{
//your logic here...
Console.WriteLine(target);
},null);
}
如果你需要在处理一部分就反馈到ui上就类似你上面的实现,但你写反了。
正常的应该是
void RefreshUI(string message)
{
if(control.IsInvokeRequired)
{
//this runs in a non ui thread.
Action<string> yourMethodDelegate=RefreshUI;
yourControl.Invoke(yourMethodDelegate,message);
}
else
{
//this runs in ui thread.
yourControl.Text=message;
}
}
@转角VV: 你是期望当ui上给了一个命令后,你在后台拉取一坨数据,处理完毕后更新到db中,然后ui上显式个成功或者失败么?
@Daniel Cai: ,.嗯嗯是的
@转角VV: 如果是4.0,你可以用task和cancellationtokensource一起配合完成你的场景,使用起来会简单些(控制什么时候停止),当然你也可以直接通过直接控制线程来操作,只是稍微麻烦点。
根据你的需求,就是在上面我给出的给threadpool的方法的委托方法中进行输出的处理。
ThreadPool.QueueUserWorkItem(_=>{
//your logic here
RefreshUI(isSuccess?"成功":"失败");
},null);