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里连接,谁知道的帮我下,我更新到文章了,希望后面踩到这个坑的顺利些,不要在这上面浪费时间。

 

啰嗦了这么多,我先给出暂时的解决方案,后续再补充:

  1. 使用Sql server 2008客户端
  2. 在程序中使用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

C#与SQL Server建立连接出错

在sql server 2000上用sa登录sql查询分析器的时候报错:无法打开用户默认数据库

已成功与服务器建立连接,但是在登录前的握手期间发生错误。

SqlServer2008用新建的别名登陆不了怎么解决呢?

sqlserver2008R2连接数据库异常,异常内容如下