对delegate进行扩展 打造通用的计时完成方法
连接数据库是程序员经常要做的事情, 通常情况下, 需要连接SQL Server中哪个数据库是已知的, 用户在输入SQL Server的服务器IP、用户名、密码和数据库名字后, 如果所有信息输入正确, 就可以建立连接了.
让用户尽量少打字
每次让用户输入这么多信息的确很糟糕, 可以改进一下设计: 服务器IP和用户名可以存放在配置文件里面, 初始化的时候默认加载到相应的文本框中; 从安全角度考虑, 密码必须经过用户手动输入; 而数据库名字则没必要让用户输入, 有了服务器IP、用户名、密码后可以尝试连接SQL Server, 连接SQL Server成功后, 把数据库中所有的数据库名加载到ComboBox让用户选择连接哪个数据库.
密码不正确
密码正确
如何实现
在后台代码中定义一个计时器, 设置它的Interval为1000毫秒, 用户输入密码时让定时器重新计时, 也就是说用户输入密码后, 如果在1秒钟内用户没有继续输入密码, 则会触发计时器的Elapsed事件, 这时程序尝试能不能连上SQL Server.
//用户停止输入密码1秒后自动尝试连接
private System.Timers.Timer m_timer=new System.Timers.Timer(1000);private void txtPassword_PasswordChanged(object sender, RoutedEventArgs e)
{m_timer.Stop();m_timer.Start();//清空数据库的选择列表cbbDatabase.Items.Clear();
}
在计时器的Elapsed事件函数中, 程序尝试连接SQL Server, 但是如下写法会出现问题.
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{Dispatcher.BeginInvoke((Action)delegate(){var conStr = String.Format("Data Source={0};Integrated Security=False;User ID={1};Password={2};", txtServer.Text, txtUser.Text, txtPassword.Password);using (var con = new SqlConnection(conStr)){try{con.Open();}catch{//TODO: 提示连接数据库失败return;}//TODO:提示连接数据库成功var sql = "select name from sys.databases";var cmd = new SqlCommand(sql, con);IAsyncResult asyncResult = cmd.BeginExecuteReader();SqlDataReader reader = cmd.EndExecuteReader(asyncResult);if (!reader.HasRows){//TODO: 提示SQL Server中不存在数据库return;}//TODO: 在这里释放Timerwhile (reader.Read()){cbbDatabase.Items.Add(reader[0].ToString());}}});
}
如果数据库的IP是错误的, con.Open()则要花费约30秒左右才会抛出异常, 这段时间UI线程会一直卡死, 经过测试, 30秒后才抛异常与数据库连接字符串的Connect Timeout属性没有关系.
可以写一个SqlConnection的扩展方法, 在这个方法里面用一个码表对执行con.Open()的时间计时, 用一个bool型变量标识有没有成功的con.Open(), 如果在规定的时间内没有成功连上SQL Server则抛出一个异常.
扩展SqlConnection
public static class SqlExtension
{public static void TryOpen(this SqlConnection connection, int millisecondTimeout){Stopwatch sw = new Stopwatch();bool succeed = false;Thread t = new Thread(() =>{try{sw.Start();connection.Open();//打开连接后设置succeed为truesucceed = true;}catch{}});t.IsBackground = true;t.Start();t.Join(millisecondTimeout);t.Abort();//如果没有成功, 则抛出一个异常if (!succeed)throw new Exception();}
}
这样在原来的代码中调用con.TryOpen()就可以解决问题.
扩展delegate
其实扩展方法的第一个参数并不是一定要是一个class类, 其实delegate也是可以的, delegate其实在编译之后就是一个类, 如下改写刚刚的SqlConnection扩展方法, 就可以写一个通用的尝试操作的扩展方法.
public static class ActionExtension
{public static void Invoke(this Action action, int millisecondTimeout){Stopwatch sw = new Stopwatch();bool succeed = false;Thread t = new Thread(() =>{try{sw.Start();action();succeed = true;}catch{}});t.IsBackground = true;t.Start();t.Join(millisecondTimeout);if (!succeed)throw new Exception();}
}
这样写, 代码则更为通用一些, 以后一些耗时的操作(当然要满足Action的签名)都可以调用这个方法, 在本例中, 可以如下调用:
((Action)con.Open).Invoke(2000);
对delegate进行扩展 打造通用的计时完成方法相关推荐
- 如何一个模型走天下?集成训练多数据集,打造通用目标检测模型方法详解
在目标检测的实际应用中,常常会出现需要泛化的目标检测系统的情况.如城市安防中,需要目标检测系统能够检测足够多类别的目标,才能达到更好的安防效果. 但目前常用的目标检测数据集中包含的类别数量有限,使用单 ...
- springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)
springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) 参考文章: (1)springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版) ( ...
- jdbc增删改查有哪些步骤_JDBC打造通用增删改方法
[JDBC]打造通用增删改方法原创 简介:在我们学习JDBC的时候或者编写简单的Servlet程序的时候,经常需要增删改查等操作,很多小伙伴的做法是:增删改查各写一个方法,这样写虽然可以实现我们想要的 ...
- 08_android_打造通用svg地图自定义组件
android_打造通用svg地图自定义组件 一.地图svg数据准备 这里笔者已经整理了云南省16个地州.129个县的svg path数据,如果你要绘制的是其他省份,甚至是中国地图,那么可以从下面这个 ...
- 最新web/springboot打造通用的短信验证码微服务(详细)
前言 很久之前的一篇文章, 最新web/java/jsp实现发送手机短信验证码和邮箱验证码的注册登录功能(详细),截止到目前,依然有很多小伙伴,私信需要帮助,于是我再加一篇,让大家能更好的使用.(当然 ...
- 这样设计一个可扩展、通用的、健壮性组件
点击上方关注 小生方勤,一起学习,天天进步 前言 组件是页面不可或缺的部分,而设计组件就成为了前端同学每日工作. 所以 一位程序员的职业生涯大约十年,只有人寿命的十分之一.前端项目只是你生活工作的一部 ...
- 旷视科技为何战略投资Video++?版图扩展打造AI+IoT 闭环 | 专访唐文斌
"AI+文娱",是一个千亿级的新兴市场,承载着新的广告.电商.互动娱乐等业务. 新智元获悉,极链科技Video++于近日完成由阿里巴巴.云锋基金.Face++旷视科技领投,国投.头 ...
- 通用的产品功能设计方法
通用的产品功能设计方法 1.如何设计注册/登录功能 1.1 注册功能设计 1.2 登录功能的设计 2.如何设计APP启动页功能和引导页功能 2.1 启动页功能设计 2.2 引导页功能设计 3.如何设计 ...
- 解决删除U盘时提示无法停止‘通用卷’设备的方法
解决删除U盘时提示无法停止'通用卷'设备的方法 文章分类:JavaEye 关键字: u盘停止'通用卷' 删除U盘时提示无法停止'通用卷'设备的解决方法 安全删除U盘时,大家常常会遇到提示"无 ...
最新文章
- 深度学习中的优化算法之BGD
- 《FPGA全程进阶---实战演练》第一章之如何学习FPGA
- C六:指针可以比较大小
- 文件内容、关键字匹配,split 和 indexOf 均可实现
- c++ 原子操作 赋值_原子操作原理
- C++多线程强制终止
- 清华,北大坐实亚洲大学Top2,泰晤士2020亚洲大学榜
- Git Stash的使用方法与注意事项
- MyBatis使用动态SQL语句
- php---兄弟连的php培训视频的总结(1)
- (一)密码学之数论基础
- 怎样设计访谈提纲_如何设计调查问卷与访谈提纲要点分析.ppt
- 征途服务器维护时间,征途私服服务器维护是什么问题
- Ubuntu系统Vscode安装以及配置C++环境(一条龙服务)
- springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码)
- 酷派大观4 8970 刷android 4.4,极速达百兆! 移动4G版酷派大观4网络体验
- android模拟器访问本地网站
- idea :不支持发行版本11问题
- 读 Flink 源码,肝进阿里云 Flink 组了。。
- djangoday02
热门文章
- 13种编程语言名称的来历
- [译] 数据可视化教程:基于Google Sheets 和 RStudio Shiny 建立实时仪表盘
- SQL Server实用操作小技巧集合
- 将sqlite查询结果导入到文本文件
- IT资产管理的演变原文-Generations of IT Asset Management
- ASP.NET 初级开发成员面试题部分面试题
- 为什么电脑不能打字_为什么新电脑不能安装win7系统?
- retract手机版怎么登录服务器未响应,retract和retreat各自的用法以及它们的区别
- indesign如何画弧线_硬币画警车简笔画【图文+视频教程】
- mysql 5.7 收费_MySQL5.7 常用用户操作