zoukankan      html  css  js  c++  java
  • winform 异步读取数据 小实例

    这几天对突然对委托事件,异步编程产生了兴趣,大量阅读前辈们的代码后自己总结了一下。

    主要是实现 DataTable的导入导出,当然可以模拟从数据库读取大量数据,这可能需要一定的时间,然后 再把数据导入到xml excel等。做了个小实例模拟了一下。特此帖出来以便日后查阅

    先上效果图

    然后贴上代码

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Diagnostics;
      6 using System.Drawing;
      7 using System.Linq;
      8 using System.Runtime.Remoting.Messaging;
      9 using System.Text;
     10 using System.Threading;
     11 using System.Windows.Forms;
     12 
     13 namespace AsyncCallBack用法
     14 {
     15     public partial class FrmMain : Form
     16     {
     17         public FrmMain()
     18         {
     19             InitializeComponent();
     20         }
     21 
     22         /// <summary>
     23         /// 定义字段来存放读取到的数据
     24         /// </summary>
     25         DataTable dtInput = new DataTable();
     26         /// <summary>
     27         /// 定义字段来存放写入的数据
     28         /// </summary>
     29         DataTable dtOutput = new DataTable();
     30 
     31         /// <summary>
     32         /// 按钮单击事件
     33         /// </summary>
     34         /// <param name="sender"></param>
     35         /// <param name="e"></param>
     36         private void button1_Click(object sender, EventArgs e)
     37         {
     38             //先记录下时间
     39             Stopwatch sw = Stopwatch.StartNew();
     40             //定义一个委托变量用来生成数据
     41             Func<int, DataTable> func = GetTableData;
     42             //异步开始
     43             func.BeginInvoke(100, ImproveTable, null);
     44             //记录时间
     45             sw.Stop();
     46             //测试异步会不会卡UI界面
     47             string times = sw.ElapsedMilliseconds.ToString();
     48             MessageBox.Show("点按钮到我弹出来总共用了"+times+"毫秒证明异步调用不会卡到主线程");
     49         }
     50        
     51         /// <summary>
     52         /// 这是回调函数
     53         /// </summary>
     54         /// <param name="iar"></param>
     55         public void ImproveTable(IAsyncResult iar)
     56         {
     57              int i = 0;
     58             if(iar!=null)
     59             {
     60                 AsyncResult ar = iar as AsyncResult;
     61                 Func<int, DataTable> func = ar.AsyncDelegate as Func<int, DataTable>;
     62                 dtInput = func.EndInvoke(iar);
     63 
     64                 DataTable dtCopy = dtInput.Copy();
     65                 dtOutput = dtInput.Clone();
     66 
     67                 //防止跨线程访问控件,利用lambda表达式,也可以直接定义一个委托实例去完成他
     68                 if (progressBar.InvokeRequired)
     69                 {
     70                     progressBar.Invoke(new Action(() => { progressBar.Maximum = dtCopy.Rows.Count; }));
     71                 }
     72                 else
     73                 {
     74                     progressBar.Maximum = dtCopy.Rows.Count;
     75                 }
     76 
     77                 foreach (DataRow dr in dtCopy.Rows)
     78                 {
     79                     Thread.Sleep(100);
     80                     i++;
     81                     dtOutput.ImportRow(dr);
     82 
     83                     //防止跨线程访问控件,
     84                     if (progressBar.InvokeRequired)
     85                     {
     86                         progressBar.Invoke(new Action(() => { progressBar.Value = i; }));
     87                     }
     88                     else
     89                     {
     90                         progressBar.Value = i;
     91                     }
     92 
     93 
     94                     if (label1.InvokeRequired)
     95                     {
     96                         label1.Invoke(new Action(() => { label1.Text = ((i) != dtCopy.Rows.Count) ? "正在写入数据,写入行数" + i.ToString() + "..." : "数据写入完毕"; }));
     97                     }
     98                     else
     99                     {
    100                         label1.Text = ((i) != dtCopy.Rows.Count) ? "正在写入数据,写入行数" + i.ToString() + "..." : "数据写入完毕";
    101                     }
    102                 }
    103             }
    104             MessageBox.Show(String.Format("我复制到了{0}行数据,我睡了{1}秒",dtOutput.Rows.Count.ToString(),(i/2).ToString()));
    105         }
    106        
    107         /// <summary>
    108         /// 生成数据的方法
    109         /// </summary>
    110         /// <param name="rows"></param>
    111         /// <returns></returns>
    112         public DataTable GetTableData(int rows)
    113         {
    114 
    115             string strColumns = "ID,Name,Gender";
    116             string[] strCol = strColumns.Split(new char[] { ',' });
    117 
    118             DataTable dt = new DataTable();
    119 
    120             for (int i = 0; i < strCol.Length; i++)
    121             {
    122                 dt.Columns.Add(strCol[i]);
    123             }
    124 
    125             //防止跨线程访问控件,
    126             if(progressBar.InvokeRequired)
    127             {
    128                 progressBar.Invoke(new Action(()=>{progressBar.Maximum=rows;}));
    129             }
    130             else
    131             {
    132                 progressBar.Maximum = rows;
    133             }
    134 
    135             Random r = new Random();
    136             for (int i = 0; i < rows; i++)
    137             {
    138                 Thread.Sleep(100);
    139                
    140 
    141                 string id = r.Next(0, 100).ToString() + "ID";
    142                 string name = r.Next(200, 300).ToString() + "Name";
    143                 string gender = r.Next(4000, 111111).ToString() + "Gender";
    144 
    145                 dt.Rows.Add(new string[] { id, name, gender });
    146 
    147                 //防止跨线程访问控件,
    148                 if (progressBar.InvokeRequired)
    149                 {
    150                     progressBar.Invoke(new Action(() => { progressBar.Value = i+1; }));
    151                 }
    152                 else
    153                 {
    154                     progressBar.Value = i+1 ;
    155                 }
    156 
    157 
    158                 if (label1.InvokeRequired)
    159                 {
    160                     label1.Invoke(new Action(() => { label1.Text = ((i+1)!= rows) ? "正在读取数据读取行数" + i.ToString() + "..." : "数据读取完毕"; }));
    161                 }
    162                 else
    163                 {
    164                     label1.Text = ((i+1) != rows) ? "正在读取数据读取行数" + i.ToString() + "..." : "数据读取完毕";
    165                 }
    166             }
    167             return dt;
    168         }
    169     }
    170 }

    关于代码的分析有时间再写。

    代码里面主要用到了BeginInvoke  EndInvoke  关于 EndInvoke放在回调函数里面的代码是从博友那里学的。

    关于用lambda表达式更新ProgressBar控件的方法也是从博友那里学的。

    个人感觉写比冗余,等以后对.net 的熟练度提高以后看这些代码可能会感觉很小白。

    如果有错误之处,请博友们指正,以防误导新人,同时也能提醒我。

    -----------------------------唯有自身强大,才能不惧外物。 http://www.cnblogs.com/lclblog/
  • 相关阅读:
    查看数据表的信息
    HR面试必问:你什么时候能到岗?聪明人都这样回答
    42种常见的HTTP响应代码
    Ubuntu环境下微信界面中间显示黑框和字体显示为白框等问题
    C# 开发电子印章制作工具 -- 附下载程序
    ofd文件拆分合并思路探索 -- 附下载程序
    利用防火墙出站规则解决Adobe Rader XI闪退问题
    记一次 Aximp.exe工具的使用
    MacOS Monterey 一键重置系统
    macbook m1 键盘进灰导致个别按键不灵敏解决方法
  • 原文地址:https://www.cnblogs.com/lclblog/p/4727574.html
Copyright © 2011-2022 走看看