这篇文章主要介绍了如何判断WebBrowser浏览器网页加载完成,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
很多人认为 SqlConnection 的连接是不耗时的,理由是循环执行 SqlConnection.Open 得到的平均时间几乎为0,但每次首次open 时,耗时又往往达到几个毫秒到几秒不等,这又是为什么呢?
首先我们看一下 MSDN 上的权威文档上是怎么说的
Connecting to a database server typically consists of several time-consuming steps. A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on.
以上摘自 http://msdn.microsoft.com/en-us/library/8xx3tyca%28VS.80%29.aspx
也就是说物理连接建立时,需要做和服务器握手,解析连接字符串,授权,约束的检查等等操作,而物理连接建立后,这些操作就不会去做了。这些操作是需要一定的时间的。所以很多人喜欢用一个静态对象存储 SqlConnection 来始终保持物理连接,但采用静态对象时,多线程访问会带来一些问题,实际上,我们完全不需要这么做,因为 SqlConnection 默认打开了连接池功能,当程序 执行 SqlConnection.Close 后,物理连接并不会被立即释放,所以这才出现当循环执行 Open操作时,执行时间几乎为0.
下面我们先看一下不打开连接池时,循环执行 SqlConnection.Open 的耗时
复制代码 代码如下:
public static void OpenWithoutPooling()
{
string connectionString = "Data Source=192.168.10.2; Initial Catalog=News;Integrated Security=True;Pooling=False;";
Stopwatch sw = new Stopwatch();
sw.Start();
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
sw.Stop();
Console.WriteLine("Without Pooling, first connection elapsed {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < 100; i++)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
}
sw.Stop();
Console.WriteLine("Without Pooling, average connection elapsed {0} ms", sw.ElapsedMilliseconds / 100);
}
SqlConnection 默认是打开连接池的,如果要强制关闭,我们需要在连接字符串中加入 Pooling=False
调用程序如下:
复制代码 代码如下:
Test.SqlConnectionTest.OpenWithoutPooling();
Console.WriteLine("Waiting for 10s");
System.Threading.Thread.Sleep(10 * 1000);
Test.SqlConnectionTest.OpenWithoutPooling();
Console.WriteLine("Waiting for 600s");
System.Threading.Thread.Sleep(600 * 1000);
Test.SqlConnectionTest.OpenWithoutPooling();
下面是测试结果
Without Pooling, first connection elapsed 13 ms
Without Pooling, average connection elapsed 5 ms
Wating for 10s
Without Pooling, first connection elapsed 6 ms
Without Pooling, average connection elapsed 4 ms
Wating for 600s
Without Pooling, first connection elapsed 7 ms
Without Pooling, average connection elapsed 4 ms
从这个测试结果看,关闭连接池后,平均每次连接大概要耗时4个毫秒左右,这个就是建立物理连接的平均耗时。
下面再看默认情况下的测试代码
复制代码 代码如下:
public static void OpenWithPooling()
{
string connectionString = "Data Source=192.168.10.2; Initial Catalog=News; Integrated Security=True;";
Stopwatch sw = new Stopwatch();
sw.Start();
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
sw.Stop();
Console.WriteLine("With Pooling, first connection elapsed {0} ms", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < 100; i++)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
}
sw.Stop();
Console.WriteLine("With Pooling, average connection elapsed {0} ms", sw.ElapsedMilliseconds / 100);
}
调用代码
复制代码 代码如下:
Test.SqlConnectionTest.OpenWithPooling();
Console.WriteLine("Waiting for 10s");
System.Threading.Thread.Sleep(10 * 1000);
Test.SqlConnectionTest.OpenWithPooling();
Console.WriteLine("Waiting for 600s");
System.Threading.Thread.Sleep(600 * 1000);
Test.SqlConnectionTest.OpenWithPooling();
测试结果
With Pooling, first connection elapsed 119 ms
With Pooling, average connection elapsed 0 ms
Waiting for 10s
With Pooling, first connection elapsed 0 ms
With Pooling, average connection elapsed 0 ms
Waiting for 600s
With Pooling, first connection elapsed 6 ms
With Pooling, average connection elapsed 0 ms
这个测试结果看,第一次耗时是119ms,这是因为我在测试代码中,首先运行的是这个测试过程,119 ms 是程序第一次启动时的首次连接耗时,这个耗时可能不光包括连接数据库的时间,还有 ado.net 自己初始化的用时,所以这个用时可以不管。10秒以后在执行这个测试过程,首次执行的时间变成了0ms,这说明连接池机制发生了作用,SqlConnection Close 后,物理连接并没有被关闭,所以10秒后再执行,连接几乎没有用时间。
但我们发现一个有趣的现象,10分钟后,首次连接时间变成了6ms,这个和前面不打开连接池的测试用时几乎一样,也就是说10分钟后,物理连接被关闭了,又重新打开了一个物理连接。这个现象是因为连接池有个超时时间,默认情况下应该在5-10分钟之间,如果在此期间没有任何的连接操作,物理连接就会被关闭。那么我们有没有办法始终保持物理连接呢?方法是有的。
连接池设置中有一个最小连接池大小,默认为0,我们把它设置为大于0的值就可以保持若干物理连接始终不释放了。看代码
复制代码 代码如下:
public static void OpenWithPooling(int minPoolSize)
{
string connectionString = string.Format("Data Source=192.168.10.2; Initial Catalog=News; Integrated Security=True;Min Pool Size={0}",minPoolSize);
Stopwatch sw = new Stopwatch();
sw.Start();
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
sw.Stop();
Console.WriteLine("With Pooling Min Pool Size={0}, first connection elapsed {1} ms",minPoolSize, sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < 100; i++)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
}
}
sw.Stop();
Console.WriteLine("With Pooling Min Pool Size={0}, average connection elapsed {1} ms",minPoolSize, sw.ElapsedMilliseconds / 100);
}
其实只要在连接字符串中加入一个 Min Pool Size=n 就可以了。
调用代码
复制代码 代码如下:
Test.SqlConnectionTest.OpenWithPooling(1);
Console.WriteLine("Waiting for 10s");
System.Threading.Thread.Sleep(10 * 1000);
Test.SqlConnectionTest.OpenWithPooling(1);
Console.WriteLine("Waiting for 600s");
System.Threading.Thread.Sleep(600 * 1000);
Test.SqlConnectionTest.OpenWithPooling(1);
With Pooling Min Pool Size=1, first connection elapsed 5 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms
Waiting for 10s
With Pooling Min Pool Size=1, first connection elapsed 0 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms
Waiting for 600s
With Pooling Min Pool Size=1, first connection elapsed 0 ms
With Pooling Min Pool Size=1, average connection elapsed 0 ms
我们可以看到当 Min Pool Size = 1 时,除了首次连接用时5ms以外,即便过了10分钟,用时还是0ms,物理连接没有被关闭。
多线程调用问题
多线程调用我也做了测试,这里不贴代码了,我大概讲一下结果。如果是多线程访问 SqlConnection ,注意是通过 new SqlConnection 方式访问,
那么这里有两个问题,如果后一个线程在前一个线程 Close 前调用了Open操作,那么 Ado.net 不可能复用一个物理连接,它将为第二个线程分配一个新的物理连接。如果后一个线程 Open 时,前一个线程已经 Close 了,则新的线程使用前一个线程的物理连接。也就是说,如果同时有n个线程连接数据库,最多情况下会创建n条物理连接,最少情况下为1条。如果创建n条物理连接,则用时理论上等于 n * t / cpu , n 为线程数,t 为每次创建物理连接的用时,前面测试的结果大概是5-10ms左右,cpu 为当前机器的CPU数量。另外网络,服务器的负荷也影响这个用时。为了保证在大并发时,尽量少的创建新的物理连接,我们可以适当把 Min Pool Size 调大一些,但也不要太大,因为单个机器TCP链路的数量是有限的。
感谢你能够认真阅读完这篇文章,希望小编分享的“如何判断WebBrowser浏览器网页加载完成”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。