程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#多線程|匿名委托傳參數|測試您的網站能承受的壓力|附源代碼

C#多線程|匿名委托傳參數|測試您的網站能承受的壓力|附源代碼

編輯:C#入門知識

源代碼下載:http://www.BkJia.com/uploadfile/2012/0522/20120522094839588.zip
引言
    我們一直在做網站,但在我河南這塊,對測試工作,特別是壓力測試一般都不怎麼在意,都是自己訪問一下速度不錯就行了,再就是數據庫訪問速度測試也是同樣情況
程序員在寫Sql代碼時,一般是一個人寫完之後,一運行可快完事
其實這些是不夠的,我們根本沒有進行過多用戶多線程的測試,如果是100個,一千個要同時訪問,還會有這樣的速度嗎?
我們自己反思一下是不是有這樣的經歷呢,我做的網站剛上傳服務器,打開很快,調數據庫1000條以內一秒用不了,感覺非常好,但過了不幾天,就會感覺到網站很慢很慢,於是去檢查測試
其實這些可以提前做的,我下面來實現一個多線程測試網站訪問速度的功能。
效果

\


說明:

         1.一次可以開N多個線程;

         2.可以設置要訪問的地址;

         3.可以設置要循環訪問的次數;

相關技術點:

         1.C# Winform;

          2.httpHelper類;這是我之前自己寫的一個類,大家可以參考一下(帶證書,無視編碼,設置代理等)

          3.多線程;

          4.線程之間的傳參;

          5.委托與匿名委托的使用方法;

實現步驟:

  1.新建一個CS項目,AutoFor,新建一個窗體為TextFor

  2.自己拉幾個控件實現如下界面

 \



 

 3.定義一個委托用來修改DataGridview的值,代碼如下


 //修改表格的委托
        private delegate void UpDateDgvDelegate(string msg, int rowId, string columnName);

        private UpDateDgvDelegate _upDateStateDelegate;
        //構造器
        public TextFor()
        {
            InitializeComponent();
            _upDateStateDelegate = new UpDateDgvDelegate(UpDateDgv);
        }

        /// <summary>
        /// 修改表格的行數據
        /// </summary>
        /// <param name="msg">要修改為的數據</param>
        /// <param name="rowId">行號</param>
        /// <param name="columnName">列名</param>
        private void UpDateDgv(string msg, int rowId, string columnName)
        {
            try
            {
                dgvTextFor.Rows[rowId].Cells[columnName].Value = msg.ToString();
            }
            catch { }
        }
4.在單擊開始時先生成對應的線程表格式,就是界面上的DataGridview,大家看下代碼

 

   /// <summary>
        /// 創建表格
        /// </summary>
        /// <param name="rows">生成多少行數</param>
        private void CreateTable(int rows)
        {
            DataTable dt_Sale = new DataTable();
            DataColumn dc = null;
            //線程ID
            dc = new DataColumn();
            dc.ColumnName = "線程ID";
            dc.DefaultValue = "1";
            dc.DataType = Type.GetType("System.String");
            dt_Sale.Columns.Add(dc);

            //循環類型
            dc = new DataColumn();
            dc.ColumnName = "循環類型";
            dc.DefaultValue = " ";
            dc.DataType = Type.GetType("System.String");
            dt_Sale.Columns.Add(dc);

            //當前循環次數
            dc = new DataColumn();
            dc.ColumnName = "當前循環次數";
            dc.DefaultValue = " ";
            dc.DataType = Type.GetType(" System.String");
            dt_Sale.Columns.Add(dc);

            //開始時間
            dc = new DataColumn();
            dc.ColumnName = "開始時間";
            dc.DefaultValue = " ";
            dc.DataType = Type.GetType("System.String");
            dt_Sale.Columns.Add(dc);

            //結束時間
            dc = new DataColumn();
            dc.ColumnName = "結束時間";
            dc.DefaultValue = " ";
            dc.DataType = Type.GetType("System.String");
            dt_Sale.Columns.Add(dc);

            //總用時(毫秒)
            dc = new DataColumn();
            dc.ColumnName = "總用時(毫秒)";
            dc.DefaultValue = " ";
            dc.DataType = Type.GetType("System.String");
            dt_Sale.Columns.Add(dc);


            DataRow dr = dt_Sale.NewRow();
            for (int i = 1; i < rows; i++)
            {
                dr["線程ID"] = i.ToString();
                dr["循環類型"] = "For循環";
                dr["當前循環次數"] = "0";
                dr["開始時間"] = "00:00:00";
                dr["結束時間"] = "00:00:00";
                dr["總用時(毫秒)"] = "0";
                dt_Sale.Rows.Add(dr);
                dr = dt_Sale.NewRow();
            }
            dgvTextFor.DataSource = dt_Sale;
        }

5.定義一個方法用來訪問指定的網站就是我們的實際測試這塊,

一起來看下代碼

 


[csharp]          <p>一起來看下代碼</p><div style="width: 900px;" class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="" href="javascript:void(0);"><img alt="" src="http://www.BkJia.com/uploadfile/2012/0522/20120522094847513.gif" /></a></span></div><pre> <span style="color:#808080;">///</span> <span style="color:#808080;"><summary></span><span style="color:#0800;"> 
        </span><span style="color:#808080;">///</span><span style="color:#0800;"> 執行數據  
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"></summary></span><span style="color:#0800;">  
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"><param name="dgvrowid"></span><span style="color:#0800;"> 線程號行號</span><span style="color:#808080;"></param></span><span style="color:#0800;">  
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"><param name="number"></span><span style="color:#0800;">循環總次數</span><span style="color:#808080;"></param></span><span style="color:#808080;">  
</span>        <span style="color:#00ff;">private</span> <span style="color:#00ff;">void</span> PingTask(<span style="color:#00ff;">int</span> dgvrowid, <span style="color:#00ff;">int</span> number) 
        { 
            <span style="color:#0800;">//</span><span style="color:#0800;">獲取開始時間</span><span style="color:#0800;">  
</span>            DateTime st = DateTime.Now; 
 
            <span style="color:#0800;">//</span><span style="color:#0800;">開始時間</span><span style="color:#0800;">  
</span>            <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, st.ToString(<span style="color:#8000;">"</span><span style="color:#8000;">hh-mm-ss</span><span style="color:#8000;">"</span>), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">開始時間</span><span style="color:#8000;">"</span>); 
 
            <span style="color:#00ff;">for</span> (<span style="color:#00ff;">int</span> i = <span style="color:#80080;">0</span>; i < number; i++) 
            { 
                <span style="color:#00ff;">try</span> 
                { 
                    HttpHelps hh = <span style="color:#00ff;">new</span> HttpHelps(); 
 
                    <span style="color:#0800;">//</span><span style="color:#0800;">自動訪問百度,主要是延長時間</span><span style="color:#0800;">  
</span>                    hh.GetHttpRequestStringByNUll_Get(<span style="color:#8000;">"</span><span style="color:#8000;">www.baidu.com</span><span style="color:#8000;">"</span>, <span style="color:#00ff;">null</span>); 
 
                    <span style="color:#0800;">//</span><span style="color:#0800;">當前循環次數</span><span style="color:#0800;">  
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, i.ToString(), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">當前循環次數</span><span style="color:#8000;">"</span>); 
 
                    <span style="color:#0800;">//</span><span style="color:#0800;">獲取結束時間</span><span style="color:#0800;">  
</span>                    DateTime et = DateTime.Now; 
 
                    <span style="color:#0800;">//</span><span style="color:#0800;">結束時間</span><span style="color:#0800;">  
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, et.ToString(<span style="color:#8000;">"</span><span style="color:#8000;">hh-mm-ss</span><span style="color:#8000;">"</span>), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">結束時間</span><span style="color:#8000;">"</span>); 
 
                    <span style="color:#0800;">//</span><span style="color:#0800;">總用時(毫秒)</span><span style="color:#0800;">  
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, ExecDateDiff(st, et), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">總用時(毫秒)</span><span style="color:#8000;">"</span>); 
                } 
                <span style="color:#00ff;">catch</span> { } 
            } 
 
        } 
           <p>一起來看下代碼</p><div style="width: 900px;" class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="" href="javascript:void(0);"><img alt="" src="http://www.BkJia.com/uploadfile/2012/0522/20120522094847513.gif" /></a></span></div><pre> <span style="color:#808080;">///</span> <span style="color:#808080;"><summary></span><span style="color:#0800;">
        </span><span style="color:#808080;">///</span><span style="color:#0800;"> 執行數據
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"></summary></span><span style="color:#0800;">
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"><param name="dgvrowid"></span><span style="color:#0800;"> 線程號行號</span><span style="color:#808080;"></param></span><span style="color:#0800;">
        </span><span style="color:#808080;">///</span> <span style="color:#808080;"><param name="number"></span><span style="color:#0800;">循環總次數</span><span style="color:#808080;"></param></span><span style="color:#808080;">
</span>        <span style="color:#00ff;">private</span> <span style="color:#00ff;">void</span> PingTask(<span style="color:#00ff;">int</span> dgvrowid, <span style="color:#00ff;">int</span> number)
        {
            <span style="color:#0800;">//</span><span style="color:#0800;">獲取開始時間</span><span style="color:#0800;">
</span>            DateTime st = DateTime.Now;

            <span style="color:#0800;">//</span><span style="color:#0800;">開始時間</span><span style="color:#0800;">
</span>            <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, st.ToString(<span style="color:#8000;">"</span><span style="color:#8000;">hh-mm-ss</span><span style="color:#8000;">"</span>), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">開始時間</span><span style="color:#8000;">"</span>);

            <span style="color:#00ff;">for</span> (<span style="color:#00ff;">int</span> i = <span style="color:#80080;">0</span>; i < number; i++)
            {
                <span style="color:#00ff;">try</span>
                {
                    HttpHelps hh = <span style="color:#00ff;">new</span> HttpHelps();

                    <span style="color:#0800;">//</span><span style="color:#0800;">自動訪問百度,主要是延長時間</span><span style="color:#0800;">
</span>                    hh.GetHttpRequestStringByNUll_Get(<span style="color:#8000;">"</span><span style="color:#8000;">www.baidu.com</span><span style="color:#8000;">"</span>, <span style="color:#00ff;">null</span>);

                    <span style="color:#0800;">//</span><span style="color:#0800;">當前循環次數</span><span style="color:#0800;">
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, i.ToString(), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">當前循環次數</span><span style="color:#8000;">"</span>);

                    <span style="color:#0800;">//</span><span style="color:#0800;">獲取結束時間</span><span style="color:#0800;">
</span>                    DateTime et = DateTime.Now;

                    <span style="color:#0800;">//</span><span style="color:#0800;">結束時間</span><span style="color:#0800;">
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, et.ToString(<span style="color:#8000;">"</span><span style="color:#8000;">hh-mm-ss</span><span style="color:#8000;">"</span>), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">結束時間</span><span style="color:#8000;">"</span>);

                    <span style="color:#0800;">//</span><span style="color:#0800;">總用時(毫秒)</span><span style="color:#0800;">
</span>                    <span style="color:#00ff;">this</span>.BeginInvoke(_upDateStateDelegate, ExecDateDiff(st, et), dgvrowid, <span style="color:#8000;">"</span><span style="color:#8000;">總用時(毫秒)</span><span style="color:#8000;">"</span>);
                }
                <span style="color:#00ff;">catch</span> { }
            }

        }


我來解釋下這句 //總用時(毫秒)                

   this.BeginInvoke(_upDateStateDelegate, ExecDateDiff(st, et), dgvrowid, "總用時(毫秒)");

   第一個BeginInvoke方法,是用來異步執行委托的,系統自帶方法。

  upDateStateDelegate是要執行的委托我們前面有定義

ExecDateDiff計算時間差的方法自己寫的如下代碼

 

[csharp] /// <summary>  
        /// 程序執行時間測試  
        /// </summary>  
        /// <param name="dateBegin">開始時間</param>  
        /// <param name="dateEnd">結束時間</param>  
        /// <returns>返回(秒)單位,比如: 0.00239秒</returns>  
        public static string ExecDateDiff(DateTime dateBegin, DateTime dateEnd) 
        { 
            TimeSpan ts1 = new TimeSpan(dateBegin.Ticks); 
            TimeSpan ts2 = new TimeSpan(dateEnd.Ticks); 
            TimeSpan ts3 = ts1.Subtract(ts2).Duration(); 
            return ts3.TotalMilliseconds.ToString(); 
        } 
/// <summary>
        /// 程序執行時間測試
        /// </summary>
        /// <param name="dateBegin">開始時間</param>
        /// <param name="dateEnd">結束時間</param>
        /// <returns>返回(秒)單位,比如: 0.00239秒</returns>
        public static string ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
        {
            TimeSpan ts1 = new TimeSpan(dateBegin.Ticks);
            TimeSpan ts2 = new TimeSpan(dateEnd.Ticks);
            TimeSpan ts3 = ts1.Subtract(ts2).Duration();
            return ts3.TotalMilliseconds.ToString();
        }

 

 

   注意,大家一定要記著這裡的類型要和委托的類型是一樣的,否則為出錯,而且它不會自動轉化,如果你定義的是String,傳的是int是不可以的, 要手動的去轉,這點請大家注意一下。


dgvrowid啟動線程所在DataGridview行,一行是一個線程的變化情況

"總用時(毫秒)" 列名,這裡是為了方便 大家看,使用的漢語大家見諒。

6.啟動線程,我們只要執行一個For就可以循環啟動了,大家一起來看看方法吧,

 

[csharp]  private void button3_Click(object sender, EventArgs e) 
        { 
            int count = Convert.ToInt32(txtCount.Text.Trim()); 
            int number = Convert.ToInt32(txtNumber.Text.Trim()); 
            CreateTable(count + 1); 
            //開啟number個線程  
            for (int i = 0; i < count; i++) 
            { 
                Thread pingTask = new Thread(new ThreadStart(delegate 
               { 
                   PingTask(i, number); 
               })); 
                pingTask.Start(); 
                Thread.Sleep(100); 
            } 
        } 
private void button3_Click(object sender, EventArgs e)
        {
            int count = Convert.ToInt32(txtCount.Text.Trim());
            int number = Convert.ToInt32(txtNumber.Text.Trim());
            CreateTable(count + 1);
            //開啟number個線程
            for (int i = 0; i < count; i++)
            {
                Thread pingTask = new Thread(new ThreadStart(delegate
               {
                   PingTask(i, number);
               }));
                pingTask.Start();
                Thread.Sleep(100);
            }
        }

 

我們都知道線程是不能直接傳參數的,只能傳Object,但使用匿名委托就可以解決 這個問題,方法如上面,大家看不明白的可以留言給我。

Thread.Sleep(100); 是為了讓線程正常啟動做了一個時間間隔。

大家可以根據自己的情況調整


其實這個例子不但可以實現這樣測試,大家還可以用來訪問數據庫,開上幾千個線程,看看你的Sql代碼訪問速度有多快。

個人感覺很不錯的一種壓力測試方法

希望大家多提提建議哦

 

 

作者 sufei1013

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved