彩世界开奖app官网-彩世界平台官方网址(彩票平台)
做最好的网站
来自 计算机编程 2019-12-07 01:39 的文章
当前位置: 彩世界开奖app官网 > 计算机编程 > 正文

SwingUtilities的invokeLater和invokeAndWait彩世界开奖ap

彩世界开奖app官网 1

案例

一个窗口,有叁个按键和一个label。点击开关,系统将做模拟导入数据的动作,导入数据从前必要检查实验数据的合法性。而且,检查实验数据和导入数据那多少个步骤都亟需花费一定的年华。
假若没有事情未发生前谈起的EDT的定义,那么您大概会那样做:

importBtn.addActionListener(new ActionListener() {
           @Override
            public void actionPerformed(ActionEvent e) {
                try{
                   lb.setText("1.检查数据合法性...");
                   Thread.sleep(3000);//模仿检测数据合法性
                   lb.setText("2.正在导入数据...");
                   Thread.sleep(4000);//模仿导入数据
                   lb.setText("3.导入成功!");
                }catch (InterruptedException e1) {
                   e1.printStackTrace();
                }
            }
        });

不过,假如运转一下以来,会意识境况是这么:点击开关,分界面卡住,开关变得不行接触,直到生龙活虎段时间(7秒)之后分界面显示“3.导入成功”。时期并从未显示“1.检查数据合法性”和“2.正值导入数据”。
其生机勃勃情况表明了下面说的理论:当事件派发线程中正在实践的风浪监听函数实践完结,才干实行UI组件的刷新操作,何况派发事件队列中的下叁个。

上边是校正后的代码,将耗费时间的操作放在四个新的行事线程中实施:

importBtn.addActionListener(newActionListener() {
            @Override
            public voidactionPerformed(ActionEvent e) {
                new Thread(new Runnable() {//开辟一个工作线程
                    @Override
                    public void run() {
                        try {
                            lb.setText("1.检查数据合法性...");
                           Thread.sleep(3000);//模仿检测数据合法性
                            lb.setText("2.正在导入数据...");
                           Thread.sleep(4000);//模仿导入数据
                            lb.setText("3.导入成功!");
                        } catch(InterruptedException e1) {
                           e1.printStackTrace();
                        }
                    }
                }).start();
            }
        });

彩世界开奖app官网 2

彩世界开奖app官网 3

lambda表达式重写下边包车型大巴代码

 importBtn.addActionListener(e -> {
            new Thread(() -> {
                try {
                   SwingUtilities.invokeLater(() -> lb.setText("1.检查数据合法性..."));
                    Thread.sleep(3000);//模仿检测数据合法性
                    SwingUtilities.invokeLater(()-> lb.setText("2.正在导入数据..."));
                    Thread.sleep(4000);//模仿导入数据
                   SwingUtilities.invokeLater(() -> lb.setText("3.导入成功!"));
                } catch (InterruptedExceptione1) {
                    e1.printStackTrace();
                }
            }).start();
        });

小说背景:在多数时候,超多入门不久的爱人都会问小编:小编是从别的语言转到C#开采的,有未有一点点底工性的材质给大家上学深造啊,你的框架感到一下太大了,希望有个遵纪守法的课程恐怕录制来学学就好了。
实际上只怕大家天天面临的太多东西了,感觉超级多都稀松常常了,纵然很细小的地点,或许我们都已经形成习贯了。反过来,即便大家切换成别的世界,如IOS、android,那么起初我们可能对内部非常多企划的平整不甚领悟,开始容许也是浑浑噩噩。
本篇继续上生机勃勃篇《稳中求进开拓WinForm项目(4卡塔尔(英语:State of Qatar)--Winform分界面模块的并轨应用》,继续介绍如何绳趋尺步开垦Winform项目,介绍专门的职业模块不认为奇的导入导出操作的死守实现,使得大家能够急迅,高效开采多如牛毛的模块功用。
上篇随笔大家介绍到活动代码生成的分界面如下所示,具备了导入、导出操作,那个操作是针对Excel举办的。

彩世界开奖app官网 4

结论

透过地点内容可以计算以下七个swing编制程序原则:
抱有的分界面相关的换代,都应有在 EDT 上实行
而耗费时间的后台运转,不应有在 EDT 上实践

2、Excel数据的导入操作

对峙于数据的导出操作,Excel数据的导入操作会稍稍麻烦一点,你足足供给选用二个文件,文件最棒以一定的沙盘实行导入,因而为了让顾客确认数据的得力,我们最棒能提供了二个把Excel数据显示出来再确认导入的长河,那样可以缩短导入错误数据的或是。
作者们精晓,这种大面积的导入操作,相当多政工模块只怕都要求,因而有供给思谋把它抽象出来,作为一个通用的导入模块,那样我们能够频仍选拔,特别常有益,因而我们提炼那一个通用导入的模块个性如下所示。

彩世界开奖app官网 5

Excel数据的导入模块,私下认可生成分界面包车型客车时候,也早就大器晚成并生成了,大家来探视个中的代码。

private string moduleName = "客户信息";
/// <summary>
/// 导入Excel的操作
/// </summary>          
private void btnImport_Click(object sender, EventArgs e)
{
    string templateFile = string.Format("{0}-模板.xls", moduleName);
    FrmImportExcelData dlg = new FrmImportExcelData();
    dlg.SetTemplate(templateFile, System.IO.Path.Combine(Application.StartupPath, templateFile));
    dlg.OnDataSave  = new FrmImportExcelData.SaveDataHandler(ExcelData_OnDataSave);
    dlg.OnRefreshData  = new EventHandler(ExcelData_OnRefreshData);
    dlg.ShowDialog();
}

内部FrmImportExcelData 是二个分界面根基模块中定义的三个通用导入模块,里面完成了生龙活虎部分如显示Excel数据,模板音讯涉及,保存数据的接口等操作。大家来探视它的程序运转的成效。

彩世界开奖app官网 6

内部大家透过代码 dlg.SetTemplate 钦点模板正是用来关联Excel模板音信的,大家让能够尽可能的选料准确的模板实行录入数据。
顾客通过第2的标志,内定要导入的Excel数据文件,采取文件后,数据会自动展现出来方便确认。
但大家选取保存数据的操作的时候,这些通用模块会推行保存的逻辑代码,并调用由创设者完结的代码逻辑,如下边代码的dlg.OnDataSave就是在履行保存的时候,奉行的代码逻辑,我们来探视生成的有的代码完毕。

bool ExcelData_OnDataSave(DataRow dr)
{
    bool success = false;
    bool converted = false;
    DateTime dtDefault = Convert.ToDateTime("1900-01-01");
    DateTime dt;
    CustomerInfo info = new CustomerInfo();
    info.Name = dr["姓名"].ToString();
    info.Age = dr["年龄"].ToString().ToInt32();
    info.Creator = dr["创建人"].ToString();
    converted = DateTime.TryParse(dr["创建时间"].ToString(), out dt);
    if (converted && dt > dtDefault)
    {
        info.CreateTime = dt;
    }

    success = BLLFactory<Customer>.Instance.Insert(info);
     return success;
}

我们精晓,导入的时候,是遍历每行Excel实行数据保存操作的,因而大家这里给出了一个生机勃勃行的操作代码就可以:bool ExcelData_OnDataSave(DataRow dr卡塔尔(قطر‎,里面包车型大巴逻辑,在数量保存的时候会被模块进行调用。
地点的操作,是一条条的拓宽操作,假若累加超越3条记下出错,模块提醒是或不是持续依旧退出。
那此中并不曾使用事务的操作,对于一些如Sqlite的大量的数量操作(速度升高超级快),提出选用事务举办处理,关于那些能够参谋《Winform开垦框架之通用数据导入导出操作的事务性操作完备》实行校正调节。
提起底,我们的Excel数据导入达成后,为了及时更新主分界面的数量,大家也定义了一个事件作为回调,如下所示。

dlg.OnRefreshData  = new EventHandler(ExcelData_OnRefreshData);

本条事件的实今世码就是在主分界面的多寡绑定更新。

void ExcelData_OnRefreshData(object sender, EventArgs e) { BindData(); }

稳中求进开垦WInform项目--多元文章导引:
稳中求进开荒WinForm项目(6卡塔尔--开荒使用混合式Winform模块
稳中求进开拓WinForm项目(5卡塔尔(قطر‎--Excel数据的导入导出操作
稳中求进开采WinForm项目(4卡塔尔国--Winform分界面模块的并轨应用
稳中求进开采WinForm项目(3卡塔尔国--Winform分界面层的类型规划
稳中求进开荒WinForm项目(2卡塔尔(英语:State of Qatar)--项目代码的分析
稳中求进开垦WinForm项目(1卡塔尔国--数据库设计和类型框架的浮动

尚无相比较就从未有过损害,以下是自家二种办法导入数据案例。

主题

上面到了SwingUtilities的内容。在swing编制程序中有三个编制程序原则:所有的分界面相关的翻新,都应当在 EDT 上实施,不然会产生分界面绘制现身不牢固错误。那也就表示地点代码的lb.setText("2.正值导入数据..."卡塔尔(قطر‎;应该在EDT中,而非新的劳作线程中实施。那样就应际而生了贰个恨恶:耗费时间的操作必需求在干活线程中试行,不然会合世分界面刷新不比时和卡顿的场所,而职业线程中的分界面刷新代码又会形成分界面绘制的不安静。
SwingUtilities可以缓和那一个冲突。SwingUtilities的invokeLater和invokeAndWait方法能够将三个可进行对象(Runnable)实例追加到EDT的可试行队列中。那么最后的代码应该是那样的:

importBtn.addActionListener(newActionListener() {
            @Override
            public voidactionPerformed(ActionEvent e) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                           SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public voidrun() {
                                    lb.setText("1.检查数据合法性...");
                                }
                            });
                           Thread.sleep(3000);//模仿检测数据合法性
                           SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public voidrun() {
                                   lb.setText("2.正在导入数据...");
                                }
                            });
                           Thread.sleep(4000);//模仿导入数据
                            SwingUtilities.invokeLater(newRunnable() {
                                @Override
                                public voidrun() {
                                   lb.setText("3.导入成功!");
                                }
                            });
                        } catch(InterruptedException e1) {
                           e1.printStackTrace();
                        }
                    }
                }).start();
            }
        });

1、Excel数据的导出操作

是因为我为了演示的目标,作者在客商音信表里面只是安顿性了多少个代表性的字段,下边大家来拜见代码生成工具自动生成的分界面后台代码是怎么的。

/// <summary>
/// 导出Excel的操作
/// </summary>
private void btnExport_Click(object sender, EventArgs e)
{
    string file = FileDialogHelper.SaveExcel(string.Format("{0}.xls", moduleName));
    if (!string.IsNullOrEmpty(file))
    {
        string where = GetConditionSql();
        List<CustomerInfo> list = BLLFactory<Customer>.Instance.Find(where);
        DataTable dtNew = DataTableHelper.CreateTable("序号|int,姓名,年龄,创建人,创建时间");
        DataRow dr;
        int j = 1;
        for (int i = 0; i < list.Count; i  )
        {
            dr = dtNew.NewRow();
            dr["序号"] = j  ;
             dr["姓名"] = list[i].Name;
             dr["年龄"] = list[i].Age;
             dr["创建人"] = list[i].Creator;
             dr["创建时间"] = list[i].CreateTime;
             dtNew.Rows.Add(dr);
        }

        try
        {
            string error = "";
            AsposeExcelTools.DataTableToExcel2(dtNew, file, out error);
            if (!string.IsNullOrEmpty(error))
            {
                MessageDxUtil.ShowError(string.Format("导出Excel出现错误:{0}", error));
            }
            else
            {
                if (MessageDxUtil.ShowYesNoAndTips("导出成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
                {
                    System.Diagnostics.Process.Start(file);
                }
            }
        }
        catch (Exception ex)
        {
            LogTextHelper.Error(ex);
            MessageDxUtil.ShowError(ex.Message);
        }
    }
 }

地方的代码中,FileDialogHelper.SaveExcel函数是调用公用类库模块,弹出一个接受保存文件的对话框,要是您未曾这几个类,你能够和谐丰盛代码实现那一个操作(那正是公用类库的收益,在行使的时候能够相当慢调用,减少代码,提升功用)。
然后根据客商录入的尺度检索必要的数目内容:string where = GetConditionSql();
接着正是创设五个连锁字段的表格对象:DataTableHelper.CreateTable,那在那之中也是利用公用类库来便于创造各类字段的表格,私下认可字段为字符串格式,假设急需如整形格式的,能够透过|进行私分,如“序号|int” 。
制造DataTable对象后,大家遍历对象会集,把它里面包车型地铁数额后生可畏行行的赋值给DataRow对象就能够了。

for (int i = 0; i < list.Count; i  )
{
    dr = dtNew.NewRow();
    dr["序号"] = j  ;
     dr["姓名"] = list[i].Name;
     dr["年龄"] = list[i].Age;
     dr["创建人"] = list[i].Creator;
     dr["创建时间"] = list[i].CreateTime;
     dtNew.Rows.Add(dr);
}

赋值后,就是要求把DataTable对象转变为Excel的操作进度了,这里操作分为两步,第一是成立Excel文书档案,第三个是写多少的表头和多少行音讯,也即是数据的写入操作,那当中大家把它封装在公用类Curry面,方便模块之间的调用。
导出Excel模块选拔了依照Aspose.Cell的机件进行多少的写入操作:AsposeExcelTools.DataTableToExcel2
导出达成后,大家提示客商是还是不是张开Excel文件。

if (MessageDxUtil.ShowYesNoAndTips("导出成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
{
        System.Diagnostics.Process.Start(file);
}

末段,完结功效后,大家运路程序,导出Excel数据的职能如下所示。

彩世界开奖app官网 7

彩世界开奖app官网 8

事件派发线程(EDT)

明白SwingUtilities类功效的前提是先清楚事件派发线程的定义。
当运转叁个 Swing 程序时,会自行创立八个线程。
1.主线程,担当实行main 方法。

  1. toolkit 线程,肩负捕捉系统事件,比方键盘、鼠标移动等,技士不会有其它轮代理公司码在这里个线程上实践。Toolkit线程的功力是把团结捕获的风浪传递给第多少个线程,也正是事件派发线程。
  2. 事件派发线程(EDT,Event Dispatcher Thread),看名就能够猜到其意义是用来派发事件(依据事件找到呼应的事件管理代码)的线程。EDT采取来自 toolkit 线程的平地风波,何况将这几个事件组织成一个行列,EDT的办事内容正是将那些行列中的事件根据顺序派发给相应的平地风波监听器,并且调用事件监听器中的回调函数,那也意味着,所有事件管理代码都以在EDT并不是主线程中推行。
    上边聊起EDT中保证了三个事件的行列,并且它们是比照顺序派发的。由于事件派发是单线程的操作,所以只有翘首以待前方事件监听器的回调函数试行达成,技艺够奉行组件更新的操作,以至继续派发前边的风浪。这样变成的贰个后果就是:当在八个风浪监听回调函数中做了耗费时间的操作,那么,分界面会因而停住,而且界面上享有控件失效(不可接触)。
    斩草除根那个标题标法门是:在事件处理函数少将耗费时间的操作放到新线程(通常称之为专门的工作线程)中实行,实际不是让其在EDT中施行。举例上边包车型大巴例子。

上边大家来介绍那一个在众多模块里面不以为奇的Excel导入、Excel导出操作是何许实现的。

浅析数据时间显然减小。

当自家注释代码中利用异步操作,当然,分界面会冒出假死状态。再来看看运营结果。

以下是那个测量检验工具的成套代码:

 

策动条件:20万 数据

接下去大家看看一样的数据量 SqlBulkCopy效果怎么着:

 彩世界开奖app官网 9

    /// <summary>
    /// BatchImportForm.xaml 的交互逻辑
    /// </summary>
    public partial class BatchImportForm : Window
    { 
        private static readonly string ConnStr = ConfigurationManager.ConnectionStrings["myconnStr"].ConnectionString;
        public BatchImportForm()
        {
            InitializeComponent();
        }

        private void BtnQueryImport_Click(object sender, RoutedEventArgs e)
        {
            var filePath = GetFilePath();
            if (!string.IsNullOrEmpty(filePath))
            {
                // 防止界面假死状态
                Task task = Task.Factory.StartNew(() =>
                {
                    SqlWork(filePath);
                });
            }
        }

        private string GetFilePath()
        {
            // 读取文本文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = System.Environment.CurrentDirectory  "\Resources\Txt"; // @"C:UsersWenDaoJunDocumentsVisual Studio 2015ProjectsJWellJWell.Cloud.UIResourcesTxt";
            ofd.Title = "读取文件";
            ofd.FileName = "";
            ofd.RestoreDirectory = true;
            ofd.Filter = "所有文件(*.*)|*.*|文本文件(*.txt)|*.txt";
            ofd.ValidateNames = true;
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;
            string strName = string.Empty;
            if (ofd.ShowDialog() == true)
            {
                strName = ofd.FileName;
            }
            if (strName == "")
            {
                MessageBox.Show("没有选择文件!");
                return null;
            }
            return strName;
        }

        private void BtnQueryImportTwo_Click(object sender, RoutedEventArgs e)
        {
            string filePath = GetFilePath();
            //if (!string.IsNullOrEmpty(filePath))
            //{
            //    Task task = Task.Factory.StartNew(() =>
            //      {
            //          SqlBulkWord(filePath);
            //      });

            //}
             SqlBulkWord(filePath);
        }


        /// <summary>
        /// 第一种方法
        /// </summary>
        /// <param name="fuillPath"></param>
        private void SqlWork(string fuillPath)
        {
            var lines = File.ReadAllLines(fuillPath, Encoding.Default);
            // 异步给控件赋值
            this.Dispatcher.Invoke(() => { this.JingDuOn.Maximum = lines.Length; });
            this.Dispatcher.Invoke(() => { this.LblRuKuOne.Content = lines.Length; });
            using (SqlConnection conn = new SqlConnection(ConnStr))
            {
                conn.Open();
                var t1 = DateTime.Now;
                for (int i = 0; i < lines.Length; i  )
                {
                    // 拼接数据
                    // 解析文本文件  ""号段"t"所属地区"t"号码类型"t"区号"" 
                    var strs = lines[i].Split('t');
                    var telNumber = strs[0].Trim('"');
                    var telArea = strs[1].Trim('"');
                    var telType = strs[2].Trim('"');
                    var telAreaCode = strs[3].Trim('"');
                    // 入库
                    using (SqlCommand cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = @"insert into TelNum(TelNumber,TelType,TelArea,TelAreaCode) values(@TelNumber,@TelType,@TelArea,@TelAreaCode)";
                        cmd.Parameters.Add(new SqlParameter("@TelNumber", telNumber));
                        cmd.Parameters.Add(new SqlParameter("@TelType", telArea));
                        cmd.Parameters.Add(new SqlParameter("@TelArea", telType));
                        cmd.Parameters.Add(new SqlParameter("@TelAreaCode", telAreaCode));
                        cmd.ExecuteNonQuery();
                        //异步委托 
                        this.JingDuOn.Dispatcher.Invoke(() => { this.JingDuOn.Value  = 1; });
                        this.LblJinDuOne.Dispatcher.Invoke(() => { this.LblJinDuOne.Content = i; });
                    }
                    var t2 = DateTime.Now;
                    var tsp = t2 - t1;
                    // 异步给控件赋值
                    this.LblHaoShiOne.Dispatcher.Invoke(() => { this.LblHaoShiOne.Content = tsp.TotalSeconds; });
                    this.LblZongHaoShiOne.Dispatcher.Invoke(() => { this.LblZongHaoShiOne.Content = $"倒计时{(tsp.TotalSeconds * lines.Length / (i   1))}秒完成。"; });
                }

            }
        }

        /// <summary>
        /// 第二种方法
        /// </summary>
        /// <param name="filePath"></param>
        private void SqlBulkWord(string filePath)
        {
            var lines = File.ReadAllLines(filePath, Encoding.Default);
            this.Dispatcher.Invoke(() => { this.JingDuTwo.Maximum = lines.Length; });
            this.Dispatcher.Invoke(() => { this.LblRuKuTwo.Content = lines.Length; });
            var t1 = DateTime.Now;

            // 创建入库需要的数据源 DataTable
            DataTable dt = new DataTable();
            dt.Columns.Add(new DataColumn("TelNumber", typeof(string)));
            dt.Columns.Add(new DataColumn("TelType", typeof(string)));
            dt.Columns.Add(new DataColumn("TelArea", typeof(string)));
            dt.Columns.Add(new DataColumn("TelAreaCode", typeof(string)));

            for (int i = 0; i < lines.Length; i  )
            {
                var row = dt.NewRow();
                // 拼接数据
                // 解析文本文件  ""号段"t"所属地区"t"号码类型"t"区号"" 
                var strs = lines[i].Split('t');
                row["TelNumber"] = strs[0].Trim('"');
                row["TelType"] = strs[1].Trim('"');
                row["TelArea"] = strs[2].Trim('"');
                row["TelAreaCode"] = strs[3].Trim('"');
                dt.Rows.Add(row);

                this.JingDuTwo.Dispatcher.Invoke(() => { this.JingDuTwo.Value  = 1; });
                this.LblJinDuTwo.Dispatcher.Invoke(() => { this.LblJinDuTwo.Content = i; });

            }
            var t2 = DateTime.Now;
            var tsp = t2 - t1;
            this.LblHaoShiTwo.Dispatcher.Invoke(() => { this.LblHaoShiTwo.Content = tsp.TotalSeconds; });


            // 入库计时
            var sw = new Stopwatch();
            sw.Start(); 
            using (SqlBulkCopy sbk = new SqlBulkCopy(ConnStr))
            {
                //表名
                sbk.DestinationTableName = "TelNum";
                //DataTable中的列名和数据库中列名对应
                sbk.ColumnMappings.Add("TelNumber", "TelNumber");
                sbk.ColumnMappings.Add("TelType", "TelType");
                sbk.ColumnMappings.Add("TelArea", "TelArea");
                sbk.ColumnMappings.Add("TelAreaCode", "TelAreaCode");
                sbk.WriteToServer(dt);
            }
            sw.Stop();

         this.LblZongHaoShiTwo.Dispatcher.Invoke(() => { this.LblZongHaoShiTwo.Content=sw.Elapsed.TotalSeconds; });

        }
    }

运营 结果相比较:

第生龙活虎利用相仿sql语句导入,因为日子原因,小编就从不等待程序实践完,不过作者记下了差相当的少供给多少日子,以致实践了多少时间。
导入数据共计:258113条,试行了38秒,已经入库了6971条,大致还索要1429秒。(不去思谋计算机配置,界面数据加载耗费时间等因素)

 

界面设计使用的WPF。

 

本文由彩世界开奖app官网发布于计算机编程,转载请注明出处:SwingUtilities的invokeLater和invokeAndWait彩世界开奖ap

关键词: .NET DotNet effective ja DevS