一、关于DateTime 在将DateTime类型,插入到数据库的时候,最容易出现的一种错误: “SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之间” 原因是我们在取DateTime.MinValue的值,并插入到数据库的时候,DateTime.MinValue值范围和数据库DateTime类型数据范围不一致造成的。数据库中,DateTime类型字段,最小值1/1/1753 12:00:00,而.NET Framework中,DateTime类型,最小值为1/1/0001 0:00:00,显然,超出了Sql的值的最小范围,导致数据溢出的错误。
解决方法:使用System.Data.SqlTypes.SqlDateTime.MinValue替代System.DateTime类型,这样SqlDateTime的MinValue和Sql中DateTime的范围吻合,就不会再出现以上的错误了。
二、关于跨线程调用控件的问题 在.NET 2.0中,我们常常需要在新建的线程,比如一个工作线程中访问UI控件,程序编译没有任何错误,但是在运行的时候,会抛出异常:InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。” 原因是因为:访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。
我们看看有问题的代码:建立新线程,并试图在线程中跨线程调用UI控件
[code]
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TestFunc));
thread.IsBackground = true;
thread.Start();
}
private void TestFunc()
{
Thread.Sleep(3000);
label1.Text = "ok!";
}
[/code]
这样在运行的时候,就会抛出InvalidOperationException异常。
解决方法:
方法1.关闭跨线程调用控件的检查,来屏蔽掉此异常
需要将Control.CheckForIllegalCrossThreadCalls 设为 false即可。(不推荐)
方法2.使用Control类的Invoke和BeginInvoke
为什么使用Invoke和BeginInvoke可以解决问题呢?因为Control的Invoke和BeginInvoke的参数为delegate,委托的方法是在Control的线程上执行的,也就是我们平时所说的UI线程。而控件也是在UI线程,所以不存在跨线程调用控件的问题。于是我们有了改进的代码:
[code]
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(TestFunc));
thread.IsBackground = true;
thread.Start();
}
private void TestFunc()
{
Thread.Sleep(3000);
this.Invoke(new SetLabel(SetLabelText), new string[] { "ok!" });
}
private delegate void SetLabel(string s);
private void SetLabelText(string s)
{
label1.Text = s;
}
[/code]
建立一个委托,调用Control类的Invoke方法,让UI线程去执行委托实例化的方法。这样就不会出现异常了。