C# 多线程防止界面假死的问题。。。

小酱油哇 2013-01-22 02:18:28
最近在做两个Oracle数据之间数据的转换。在转换每张表的数据时我都写了一个帮助类用来处理数据。
比如转换A表数据就实例化 ExtractDataA 类,调用其内部方法转换数据。我把这些类放在一个集合里循环执行数据的转换。在大量循环提取数据的时候会导致界面假死,不知道该怎么用多线程来处理这个问题。求大家指点。

//开始提取数据
private void btnStartExtract_Click(object sender, EventArgs e)
{
try
{
if (methodList.Count==0)
{
return;
}
this.lblDescription.Text = "正在准备提取数据...";

foreach (ExtractDataMethodClass methodItem in methodList)
{
if (methodItem.ISExcute)
{
this.lblDescription.Text= "正在执行" + methodItem.Name;
Assembly asmb = Assembly.LoadFrom(Application.StartupPath + "\\" + methodItem.DLLName);
//表示创建一个类的实例
object intance = asmb.CreateInstance(methodItem.ClassName);
if (DataExtract_SystemSetHelper.Instance.ISIncreaseMentData)
{
//执行增量提取方法
(intance as IDataExctaction).ExtractIncrementData(progressBar1,this.lblDescription);
}
else
{
//执行全量提取方法
(intance as IDataExctaction).ExtractFullData(progressBar1,this.lblDescription);
}
}
}
MessageBox.Show("完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
...全文
554 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
关注一下,我也碰到过
小酱油哇 2013-01-22
  • 打赏
  • 举报
回复
[quote=引用 3 楼 gxingmin 的回复:] 首先感谢你的帮助,我发现导致我界面假死的原因是在执行数据转换帮助类的时候,批量添加数据到oracle中时界面就会假死了,因为批量添加的那一句代码执行的时间比较长。

 /// <summary>
        /// 提取全量库
        /// </summary>
        /// <returns></returns>
        public bool ExtractFullData(ProgressBar bar,Label lab)
        {
            //略过不必要的信息。。。。

            //提取业务表的基本信息
            int InfoPagecount = DataCount / 50000 + 1;//基本信息总页数
            int successcount = 0;//成功更新到数据中心的记录

            lab.Text = "正在提取地籍登记卡数据库基本信息...";
            //分页提取数据库数据
            for (int i = 0; i < InfoPagecount; i++)
            {
                Application.DoEvents();
                int pageindex = i + 1;
                //提取要插入到B库的数据 这个时候也会假死但是时间很短
                DataTable dt = OracleHelper.Instance.GetPageTable("Cadastral_DJK", lst, pagewhere, "TBRQ desc", pageindex, 50000);
                //批量插入数到B库 就是在执行这个方法的时候界面会假死 一直到插入数据完成
                int result = ExtractData(dt, bar, lab, successcount, 0);

                lab.Text = "正在更新地籍登记卡数据库基本信息到综合搜索库...";
                int zhss = ExtractDataSearch(dt);
                successcount += result;
            }
            return true;
        }

 /// <summary>
        /// 更新基本信息到数据中心
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        private int ExtractData(DataTable dt,ProgressBar bar,Label lab,int rownum,int type) 
        {
            try
            {
                #region MyRegion
                
               
                Dictionary<string, object[]> columnRowData = new Dictionary<string, object[]>();
                DC_DJ_DJK djk = new DC_DJ_DJK();
                TableInfoDictionary.GetTableInfo(djk);

                Type typeDCDJDJK = djk.GetType();
                PropertyInfo[] proInfosDCDJDJK = typeDCDJDJK.GetProperties();
                int leng = dt.Rows.Count;
               
                foreach (PropertyInfo item in proInfosDCDJDJK)
                {
                    string name = item.Name;
                    if (item.PropertyType.Name != "Byte[]" || name == "DJKID")
                    {
                        if (name != "DJH")
                        {
                            object[] value = new object[leng];
                            columnRowData.Add(name, value);
                        }
                    }
                }
                int num = 0;
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    Application.DoEvents();
                    rownum +=1;
                    bar.Value++;
                    lab.Text = "正在提取第" + rownum + "条数据...";
                    foreach (PropertyInfo item in proInfosDCDJDJK)
                    {
                        string name = item.Name;
                        if (dt.Columns.Contains(name))
                        {
                            object value = dt.Rows[i][name];
                            if (item.PropertyType.Name == "DateTime" && value == DBNull.Value)
                            {
                                value = DateTime.MinValue;
                            }
                            columnRowData[name].SetValue(value, num);
                        }
                    }
                    num++;
                }
                #endregion
                lab.Text = "正在更新数据到监管平台...";
                int result = 0;
                if (type == 0)
                {
                    //批量插入数据到B数据库 此时界面假死 一直到该句代码执行完成
                     result = OracleHelper.Instance.BatchInsert("DC_DJ_DJK", columnRowData);
                }
                else 
                {
                    //批量更新数据到B数据库
                     result = OracleHelper.Instance.BatchUpdate("DC_DJ_DJK","DJKID",columnRowData);
                }
                return result;
            }
            catch (Exception ex)
            {
                error.Append(ex.Message + "\r\n");
                return 0;
            }
        }

  • 打赏
  • 举报
回复
private delegate void finishExtractHandler(); //开始提取数据 private void btnStartExtract_Click(object sender, EventArgs e) { try { if (methodList.Count==0) { return; } this.lblDescription.Text = "正在准备提取数据..."; Thread t = new Thread(new ThreadStart(extractDatas)); t.Start(); } catch (System.Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } private extractDatas(){ foreach (ExtractDataMethodClass methodItem in methodList) { if (methodItem.ISExcute) { this.lblDescription.Text= "正在执行" + methodItem.Name; Assembly asmb = Assembly.LoadFrom(Application.StartupPath + "\\" + methodItem.DLLName); //表示创建一个类的实例 object intance = asmb.CreateInstance(methodItem.ClassName); if (DataExtract_SystemSetHelper.Instance.ISIncreaseMentData) { //执行增量提取方法 (intance as IDataExctaction).ExtractIncrementData(progressBar1,this.lblDescription); } else { //执行全量提取方法 (intance as IDataExctaction).ExtractFullData(progressBar1,this.lblDescription); } } } this.Invoke(new finishExtractHandler(finishExtract)); } private finishExtract(){ MessageBox.Show("完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); }
gxingmin 2013-01-22
  • 打赏
  • 举报
回复
public delegate void AddControlHanddler(); //开始提取数据 private void btnStartExtract_Click(object sender, EventArgs e) { new System.Threading.Thread(new System.Threading.ThreadStart(myThread)).Start(); } private void myThread() { AddControlHanddler add = new AddControlHanddler(Func); this.Invoke(add); } //线程提取数据 private void Func() { try { if (methodList.Count==0) { return; } this.lblDescription.Text = "正在准备提取数据..."; foreach (ExtractDataMethodClass methodItem in methodList) { if (methodItem.ISExcute) { this.lblDescription.Text= "正在执行" + methodItem.Name; Assembly asmb = Assembly.LoadFrom(Application.StartupPath + "\\" + methodItem.DLLName); //表示创建一个类的实例 object intance = asmb.CreateInstance(methodItem.ClassName); if (DataExtract_SystemSetHelper.Instance.ISIncreaseMentData) { //执行增量提取方法 (intance as IDataExctaction).ExtractIncrementData(progressBar1,this.lblDescription); } else { //执行全量提取方法 (intance as IDataExctaction).ExtractFullData(progressBar1,this.lblDescription); } } Application.DoEvents(); } MessageBox.Show("完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (System.Exception ex) { MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
silentcross 2013-01-22
  • 打赏
  • 举报
回复
一般使用Backgroundworker类,需要后台执行的方法挂在DoWork事件上,调用BackgroundWork.StartAsync ()方法。 还有其他的事件,进度变化,作业完成,用户取消等,简单好用
bdmh 2013-01-22
  • 打赏
  • 举报
回复
简单说,new一个Thread,将处理方法在里面执行,如果需要操作主界面, 要用委托,google “c#线程 委托”

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧