当前位置: 首页 > news >正文

C# 如何异步查询数据库

      以前在学习Socket的时候,经常会使用到异步操作,孰不知将异步用到数据库查询上也是一把利器,特别是在大数据量查询的时候效果应该是比较明显的。我顺便写了一个小例子,供大家参考。

      我们平时默认使用的查询是同步的,也就是说一方不等待另一方做好准备,当查询时间过长时,客户端会被一直阻塞在这里而不能做其他事情。而当我们使用异步时,程序并不会阻塞或挂起线程,它会通过一个代理的回调方法完成查询,主线程将会继续执行,这样便解决了同步所不能做到的并行执行的结果。

  代码如下所示:

  

 1 public partial class AsyncSearchForm : Form
2 {
3 #region --Delegates--
4 private delegate void DisplayTimeInfoDelegate(string text);
5 private delegate void DisplayDataGridViewDelegate(DataTable myTable);
6 private delegate void DisplayInfoDelegate(string text);
7 #endregion
8
9 #region --Fields--
10 private SqlConnection mConnection;
11 private Stopwatch mWatch;
12 private DisplayTimeInfoDelegate myTimeDelegate;
13 private DisplayDataGridViewDelegate myDataDelegate;
14 #endregion
15
16 #region --Constructor--
17 public AsyncSearchForm()
18 {
19 InitializeComponent();
20 mWatch = new Stopwatch();
21 myDataDelegate = new DisplayDataGridViewDelegate(DisplayDataResults);
22 myTimeDelegate = new DisplayTimeInfoDelegate(DisplayTimeResults);
23 button_DoSearch.Click += new EventHandler(Button_DoSearch_Click);
24 }
25 #endregion
26
27 #region --Event Methods--
28 /// <summary>
29 /// 当点击执行查询时发生
30 /// </summary>
31 private void Button_DoSearch_Click(object sender, EventArgs e)
32 {
33 Application.DoEvents();
34 string connectionString = @"Data Source=127.0.0.1;Integrated Security=SSPI;Database=Northwind;Asynchronous Processing=true";
35 mConnection = new SqlConnection(connectionString);
36 string sqlString = "select * from Orders";
37 SqlCommand command = new SqlCommand(sqlString, mConnection);
38 mConnection.Open();
39 mWatch.Start();
40 AsyncCallback callBack = new AsyncCallback(HandleCallback);//注册回调方法
41 //开始执行异步查询,将Command作为参数传递到回调函数以便执行End操作
42 command.BeginExecuteReader(callBack, command);
43 }
44 #endregion
45
46 #region --Private Methods--
47 /// <summary>
48 /// 异步查询的回调方法
49 /// </summary>
50 /// <param name="MyResult">异步操作状态</param>
51 private void HandleCallback(IAsyncResult MyResult)
52 {
53 try
54 {
55 SqlCommand command = (SqlCommand)MyResult.AsyncState;
56 SqlDataReader reader = command.EndExecuteReader(MyResult);
57 mWatch.Stop();
58 string callBackTime = mWatch.ElapsedMilliseconds.ToString() + "毫秒";
59 DataTable dataTable = new DataTable();
60 dataTable.Load(reader);
61 this.Invoke(myTimeDelegate, callBackTime);
62 this.Invoke(myDataDelegate, dataTable);
63 }
64 catch (Exception MyEx)
65 {
66 this.Invoke(new DisplayInfoDelegate(DisplayTimeResults), String.Format(MyEx.Message));
67 }
68 finally
69 {
70 if (mConnection != null)
71 {
72 mConnection.Close();
73 }
74 }
75 }
76
77 /// <summary>
78 /// 在Label上显示信息
79 /// </summary>
80 /// <param name="text"></param>
81 private void DisplayTimeResults(string text)
82 {
83 this.label_Time.Text = label_Time.Text + text;
84 }
85
86 /// <summary>
87 /// 绑定数据到DataGridView
88 /// </summary>
89 /// <param name="myTable"></param>
90 private void DisplayDataResults(DataTable myTable)
91 {
92 this.dgv_Data.DataSource = myTable;
93 }
94 #endregion
95 }

  运行结果如下所示:

  代码很简单,没有很多的东西。数据库我使用了Northwind,这次查询用了4毫秒,在这样短的查询耗时下,异步对程序作用是不明显的,真正使用时还需具体问题具体分析。需要提醒大家的是异步操作是普遍存在的,但异步方式也需要某种程度的协调,异步看似效率高无阻塞,但若程序在还没得到查询结果的时候就调用了使用查询结果的方法就会出错。因此还可以使用ManualResetEvent手动给线程指定阻塞和非阻塞的信号,这样各个线程之间就可以等待彼此的信号达到同步目的,有兴趣的朋友可以试试,我在这就不再赘述了。最后送大家一句话:“异步有风险,使用需谨慎。”

转载于:https://www.cnblogs.com/yanchenglong/archive/2012/03/15/2397264.html

相关文章:

  • unity崩溃日志目录
  • Java蓝桥杯——排列组合
  • 经典bug集锦
  • javassit(1) 基础概念
  • unity中Playable的使用
  • 设计已死?
  • 镜花缘——李汝珍著
  • 破译肢体语言密码——王邈著
  • 探寻胡适的精神世界——欧阳哲生著
  • 新开通一个英文博客
  • 大宋国士——陈启文著
  • 爸爸是只“狗”——王小列著
  • 从项目中清楚ClickOnce
  • 极限运算法则
  • [VS2005 Tip] 自动生成Property。
  • 2017前端实习生面试总结
  • Django 博客开发教程 16 - 统计文章阅读量
  • JS笔记四:作用域、变量(函数)提升
  • nodejs:开发并发布一个nodejs包
  • passportjs 源码分析
  • Redis字符串类型内部编码剖析
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • vue中实现单选
  • 高性能JavaScript阅读简记(三)
  • 缓存与缓冲
  • 回顾 Swift 多平台移植进度 #2
  • 判断客户端类型,Android,iOS,PC
  • 前嗅ForeSpider中数据浏览界面介绍
  • 线性表及其算法(java实现)
  • 用element的upload组件实现多图片上传和压缩
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 从如何停掉 Promise 链说起
  • 第二十章:异步和文件I/O.(二十三)
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • (1)虚拟机的安装与使用,linux系统安装
  • (26)4.7 字符函数和字符串函数
  • (27)4.8 习题课
  • (4) PIVOT 和 UPIVOT 的使用
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (LeetCode 49)Anagrams
  • (第27天)Oracle 数据泵转换分区表
  • (六)c52学习之旅-独立按键
  • (强烈推荐)移动端音视频从零到上手(下)
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)库存超卖案例实战——优化redis分布式锁
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET Reactor简单使用教程
  • .net 简单实现MD5
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • @EnableAsync和@Async开始异步任务支持
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [120_移动开发Android]008_android开发之Pull操作xml文件