zoukankan      html  css  js  c++  java
  • 大容量数据传输UI无响应怎么办:异步查询大结果集!

    数据库管理程序中,如果涉及大容量的数据传输,在数据检索过程中可能导致UI无响应。这里模拟这个过程,并通过异步调用避免UI停滞问题。
    该示例有共有3个button和1个DataGridView控件,其中2个button用于分别正常检索数据和异步检索数据,另一个button用于绑定数据。
    异步调用实际是开启新的非UI线程处理数据,因此异步调用中弹出的对话框也是和用户UI没关系的。程序中让数据访问延时5秒,尝试拖动窗体看看效果。


    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.Data.SqlClient;
    using System.Collections;

    namespace snippetWinForm
    {
        
    public partial class frmSnippet : Form
        {
            
    public frmSnippet()
            {
                InitializeComponent();
            }

            
    //Variable declaration
            string connectionString = "Data Source=.\\sqlexpress; Initial Catalog=Northwind; Integrated security=true;Asynchronous Processing=true";
            
    string selectString = "waitfor delay  '0:0:5'; select productname, quantityPerUnit, unitPrice, unitsInStock, UnitsOnOrder from products;  ";
            ArrayList al 
    = new ArrayList();

            
    /// <summary>
            
    /// 加载数据,并填充到ArrayList对象; 
            
    /// 此为非异步调用,所以大容量数据时可能UI停止响应;
            
    /// 如MessageBox弹出后绑定按钮无法按下。
            
    /// </summary>
            private void btnLoad_Click(object sender, EventArgs e)
            {
                al.Clear();
                
    using (SqlConnection  cn = new SqlConnection(connectionString))
                {
                    SqlCommand  cmd 
    = new SqlCommand(selectString, cn);
                    cn.Open();

                    SqlDataReader dr 
    = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                    
    if (dr.HasRows )
                    {
                        
    foreach (var item in dr)
                        {
                            al.Add(item);
                        }
                        dr.Close();
                    }
                    cn.Close();
                }
                MessageBox.Show(
    "UI  Thread:Data Load finished, you can bind the data now!""Data Load");
            }


            
    /// <summary>
            
    /// 异步调用唤起,命令对象cmd执行完毕后执行异步回调AsyncCallback callback
            
    /// </summary>
            private void btnLoadDataAsync_Click(object sender, EventArgs e)
            {
                al.Clear(); 
                SqlConnection  cn 
    = new SqlConnection(connectionString);//此处若用using语句包括,将无法实现异步调用!!!
                {
                    SqlCommand  cmd 
    = new SqlCommand(selectString, cn);
                    cn.Open();

                    AsyncCallback callback 
    = new AsyncCallback(DataReaderIsReady);
                    IAsyncResult asyncResult 
    = cmd.BeginExecuteReader(callback, cmd);
                }
            }


            
    /// <summary>
            
    /// 回调方法,在命令cmd执行完毕后调用该callback方法;
            
    /// AsyncCallback callback = new AsyncCallback(DataReaderIsReady);
            
    /// IAsyncResult asyncResult = cmd.BeginExecuteReader(callback, cmd);
            
    /// </summary>
            
    /// <param name="result"></param>
            private void DataReaderIsReady(IAsyncResult result)
            {
                
    //因为是异步调用,所以这个MessageBox是非模式的对话框,可以继续点击UI。
                
    //问题:在MessageBox显示的时候点击绑定按钮(此时ArrayList为空),然后确定MessageBox,此时尽管ArrayList有数据,但也无法绑定,WHY?
                MessageBox.Show("Asynchronous callback ,None UI Thread : Result Load Complete!""I'm Done!");
                SqlCommand  cmd 
    = (SqlCommand)result.AsyncState;
                SqlDataReader dr 
    = cmd.EndExecuteReader(result);

                
    if (dr.HasRows)
                {
                    
    foreach (var item in dr)
                    {
                        al.Add(item);
                    }
                }
                dr.Close();
                cmd.Connection.Dispose();

                
    //btnBind.Enabled = true; //因为该方法在另外的非UI先线程里,所以对btnBind不可见!
            }        
            
            
    /// <summary>
            
    /// 只需要将DataGridView的DataSource指定为ArrayList对象,就完成了绑定。
            
    /// </summary>
            private void btnBind_Click(object sender, EventArgs e)
            {
                dgvProducts.DataSource 
    = al;
            }
        }
    }
  • 相关阅读:
    bootstrap媒体查询
    Qt用Zip压缩文件夹的一些坑
    QCanvasItem介绍-QT3
    C盘无损扩容
    ArcGis连接oracle失败:ORA-6413:连接未打开
    通过ArcMap发布服务
    windows系统下使用cd命令
    C语言运算符优先级
    c/c++ 指针
    c++数组易错点总结
  • 原文地址:https://www.cnblogs.com/flaaash/p/1978462.html
Copyright © 2011-2022 走看看