C#程序访问SQL2008报错:已成功与服务器建立联系,但登陆前握手期间发生错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#程序访问SQL2008报错:已成功与服务器建立联系,但登陆前握手期间发生错误相关的知识,希望对你有一定的参考价值。
我用C#写了一个接口,别人调这个接口就能向服务器上的数据库插入查询数据。但是每天都会接到一些报错邮件。时间间隔发生在几分钟内,其他时间正常,报错邮件显示错误信息有两种:A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - The wait operation timed out.) 登录前发生了握手错误。要不就显示在查询数据时:The wait operation timed out.。我已查看了数据库的配置,超时设置都没有问题。http://blog.csdn.net/piaoshisun/article/details/6029174。这个帖子我也看过了,没什么帮助。实在没有头绪,求指教,多谢
一:线程在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
不带参数的启动方式
如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread:
带参数的启动方法
带参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同 的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。 为 什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接 口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类) 等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。
这种object类型的参数可以定义一个有多个属性的类来进行,或者用$隔开的字符串,使用的时候分解为数组来用
简单实例代码:
//不带参数
ThreadStart ts = new ThreadStart(ThreadFunc);
Thread t = new Thread(ts);
t.Start();
//带参数
ParameterizedThreadStart ParStart = new ParameterizedThreadStart(GoTo);
Thread myThread = new Thread(ParStart);
object o = (object)txt_url.Text;
myThread.Start(o);
详细实例代码:
Program p = new Program();
Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));
nonParameterThread.Start();
Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));
parameterThread.Name = "Thread A:";
parameterThread.Start(30);
/// <summary>
/// 不带参数的启动方法
/// </summary>
public void NonParameterRun()
for (int i = 0; i < 10; i++)
Console.WriteLine("系统当前时间毫秒值:"+DateTime.Now.Millisecond.ToString());
Thread.Sleep(200);//让线程暂停
/// <summary>
/// 带参数的启动方法
/// </summary>
/// <param name="ms">让线程在运行过程中的休眠间隔</param>
public void ParameterRun(object ms)
int j = 10;
int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常
for (int i = 0; i < 10; i++)
Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
Thread.Sleep(j);//让线程暂停
二:委托
委托就是讲方法以参数的形式进行传递
private static void WriteStrToFile(string txt)
write(txt);
private delegate void WriteStrToFileDelegate(string txt);//定义委托
new WriteStrToFileDelegate(WriteStrToFile).BeginInvoke(txt, null, null);//异步使用委托
再举一例:
public delegate void GreetingDelegate(string name);//定义委托
//定义两方法
private static void EnglishGreeting(string name)
Console.WriteLine("Morning, " + name);
private static void ChineseGreeting(string name)
Console.WriteLine("早上好, " + name);
使用:
private static void GreetPeople(string name, GreetingDelegate MakeGreeting)
MakeGreeting(name);//这里默认同步方式,与MakeGreeting.Invoke(name)效果一样
//使用
GreetPeople("Jimmy Zhang", EnglishGreeting);
GreetPeople("张子阳", ChineseGreeting);
实际上,我们可以也可以绕过GreetPeople方法,通过委托来直接调用EnglishGreeting和ChineseGreeting:
GreetingDelegate delegate1;
delegate1 = EnglishGreeting; // 先给委托类型的变量赋值
delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法
// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法
delegate1 ("Jimmy Zhang");
Console.ReadKey();
委托的Invoke方法用来进行同步调用。同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了。
异步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。
委托的异步调用通过BeginInvoke和EndInvoke来实现。
比较:
在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。
委托其实也是一个线程
MethodInvoker mi = new MethodInvoker(DoPay);//定义委托
this.BeginInvoke(mi);
这里MethodInvoker
只是一个委托, 我们可以认为所有没有参数的返回值为void的委托和 MethodInvoker 是一样的, 他们都可以委托到没有参数的返回值为void的方法。
你自己写一个 Public Delegate Sub ABC, 这个时候ABC和MethodInvoker是完全一样的。所以.Net 提供这个只是为了方便你编写,省得你自己再写一堆一样的委托了。 参考技术A 会不会是连接数超过了,或者把过期时间缩短些如何。追问
如果在那个出错期间,有人对数据库进行了大量的操作可不可能出现这种情况。
追答我的数据库操作基本都是满内存满负荷运算,也没出现过这个情况呢。 如果仅仅是那个时间段内出现这个情况。 你跟踪下SQL数据库 找到那个时间到底有些什么事情在MSSQL里发生了
追问怎么追踪SQL数据库,求教?我不太擅长数据库这的技术
追答就再这里 点进去看看 都中文的。
我按您的办法看了,不过这个profiler有办法查历史记录吗?
追答这个没办法,你可以今天开起,明天来看今天的记录。
参考技术B 贴个报错图出来vs 或 Sql server2012连接Sql server时出现的问题:已成功与服务器建立连接,但在登陆过程中发生错误
以前连接是正常的,就这两天连不上了。(没有耐心的直接看末尾解决办法)
错误消息如下:
1.尝试读取或写入受保护的内存。这通常指示其他内存已损坏。(System.Data)
2.已成功与服务器建立连接,但在登陆过程中发生错误。(provider:SSL Provider,error:0-接收到的消息异常,或格式不正确。)(Microsoft SQL Server)
然后就Management崩溃了。
没办法,那就使用vs当中的服务器资源管理器连接吧,结果可想而知,其中vs版本2008,2010,2012,2013均崩溃。无语,怎么办,联系服务器客服,说了半天,没办法,下了个Sql server2008的客户端 试试,没想到真连上了。
这不是高潮,高潮是我写代码发现ExecuteNonQuery()执行时报同样的错误,这怎么办,蛋碎。。。System.Data.SqlClient都用不了。愤怒,换成System.Data.OleDb,奇迹出现了,好了。
这一下提醒了我,然后就在vs的服务器资源管理器里设置数据源提供程序:
结果应该猜到了,正常了。
看到这里你一定以为纠结终于结束了,错,Sql server 2012里还是不可以啊,登陆界面选项里没哟设置数据源提供程序的地方,怎么办?看网上说使用Management连接其他数据库,比如连接Oracle,可以使用链接服务器连接,配置ODBC。坑爹的是ODBC都弄好的,测试都成功了,但这里就是失败。
至今没搞定从Sql server 2012 Management Studio里连接,谁知道的帮我下,我更新到文章了,希望后面踩到这个坑的顺利些,不要在这上面浪费时间。
啰嗦了这么多,我先给出暂时的解决方案,后续再补充:
- 使用Sql server 2008客户端
- 在程序中使用System.Data.OleDb代替System.Data.SqlClient
Append:
感谢高海东的解决方案,经验证,确实是迅雷引起的异常,卸载掉迅雷的所有产品后,问题得到解决。
疑惑的是之前也在使用迅雷,或许是迅雷自动更新的某些组件引起的,记得当时win8刚出来时,迅雷也引起IE10崩溃。具体原理就不得而知了,先这样吧。
感谢 jaypgcool :也许是迅雷更改了winsock的某些设置,重置了一下winsock就OK了,命令:netsh winsock reset
以上是关于C#程序访问SQL2008报错:已成功与服务器建立联系,但登陆前握手期间发生错误的主要内容,如果未能解决你的问题,请参考以下文章
sql server 2008启动时:已成功与服务器建立连接,但是在登录过程中发生错误。(provider:命名管道提供程序,error:0-管道的另一端上无任何进程。)(Microsoft SQL