[C#]善用 TPL 非同步設計

[C#]善用 TPL 非同步設計

.net4.0 後新推出TPL非同步利器,實務上只要專案使用.net4.0以上,

我都會使用TPL撰寫非同步,如遇舊專案使用ThreadPool或是IAsyncResult Interface,

大致上我也會一併改寫為TPL,至於為什麼要用TPL開發呢?

主要就是提高效能,現實世界中,

ViewModel不太可能單純只有單一資料來源或資料查詢單一作業,

可能還有下拉選單資料、其他系統介接資料、systemlog作業...等相關操作和其他資料,

這篇我簡單使用asp.net mvc with TPL測試一下同步和非同步兩者效能差異。

 

View


@model KOTSMS.Models.IndexBViewModel
@{
    ViewBag.Title = "TPL非同步測試";
}

<h2>TPL非同步測試</h2>

    @if(Model!=null)
    {
    <p>
<span>公司:</span>@Html.DropDownListFor(m => m.companys, Model.companys);
<span>職稱:</span>@Html.DropDownListFor(m => m.titles, Model.titles);
        <span>班別:</span>@Html.DropDownListFor(m => m.branchs, Model.branchs);
        <span>部門:</span>@Html.DropDownListFor(m => m.departs, Model.departs);
</p>
<span>平均花費時間(ms):@Html.Raw(Model.Avgtime)</span>
    <table>
        <thead>
            <tr>             
                <th>C1</th>    
                <th>C2</th>
                <th>C3</th>
                <th>C4</th>
                <th>C5</th>
                <th>C6</th>                    
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.kpis)
            { 
            <tr>
                <td>@Html.Raw(item.KPI_FNAME)</td>
                <td>@Html.Raw(item.KPI_M_name)</td>
                <td>@Html.Raw(item.KPI_D_name)</td>
                <td>@Html.Raw(item.KPI_D_weight)</td>
                <td>@Html.Raw(item.KPI_SUBD_Name)</td>
                <td>@Html.Raw(item.KPI_SUBDESC_Name)</td>               
            </tr>            
            }
        </tbody>
    </table>
    }
    

 

Controller


public ActionResult IndexB(string optype)
        {
            IndexBViewModel _IndexBViewModel = new IndexBViewModel();
            int totalavg = 0;
            if (optype == "async")
            {
                for (int i = 0; i < 5; i++)
                {
                     Async(_IndexBViewModel);
                    totalavg += int.Parse(_IndexBViewModel.costtime);
                }
                ViewData.Model = _IndexBViewModel;            
            }
            else
            {
                for (int i = 0; i < 5; i++)
                {
                    Sync(_IndexBViewModel);
                    totalavg += int.Parse(_IndexBViewModel.costtime);
                }
                ViewData.Model = _IndexBViewModel;
            }
            _IndexBViewModel.Avgtime = (totalavg / 5).ToString();
            return View();
        }

 


private IndexBViewModel Sync(IndexBViewModel srcvmode)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset();
            sw.Start();
            string sqlstatement = @"select * from COMPANY";
            using (SqlConnection conn = new SqlConnection(conns))
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                {
                    if (conn.State == System.Data.ConnectionState.Closed)
                        conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        if (dr.HasRows)
                        {
                            while (dr.Read())
                            {
                                ddls.Add(new SelectListItem
                                {
                                    Text = dr["name"].ToString(),
                                    Value = dr["id"].ToString()
                                });
                            }
                            srcvmode.companys = ddls.AsEnumerable();
                        }
                    }
                }
            }

            sqlstatement = @"select * from TITLE";
            using (SqlConnection conn = new SqlConnection(conns))
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                {
                    if (conn.State == System.Data.ConnectionState.Closed)
                        conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        if (dr.HasRows)
                        {
                            while (dr.Read())
                            {
                                ddls.Add(new SelectListItem
                                {
                                    Text = dr["name"].ToString(),
                                    Value = dr["id"].ToString()
                                });
                            }
                            srcvmode.titles = ddls.AsEnumerable();
                        }
                    }
                }
            }

            sqlstatement = @"select * from BRANCH";
            using (SqlConnection conn = new SqlConnection(conns))
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                {
                    if (conn.State == System.Data.ConnectionState.Closed)
                        conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        if (dr.HasRows)
                        {
                            while (dr.Read())
                            {
                                ddls.Add(new SelectListItem
                                {
                                    Text = dr["name"].ToString(),
                                    Value = dr["id"].ToString()
                                });
                            }
                            srcvmode.branchs = ddls.AsEnumerable();
                        }
                    }
                }
            }

            sqlstatement = @"select * from DEPARTMENT";
            using (SqlConnection conn = new SqlConnection(conns))
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                {
                    if (conn.State == System.Data.ConnectionState.Closed)
                        conn.Open();
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        if (dr.HasRows)
                        {
                            while (dr.Read())
                            {
                                ddls.Add(new SelectListItem
                                {
                                    Text = dr["name"].ToString(),
                                    Value = dr["id"].ToString()
                                });
                            }
                            srcvmode.departs = ddls.AsEnumerable();
                        }
                    }
                }
            }

            sqlstatement = @"USP_GetGetKPIFormData";
            List<KPIViewModel> kpis = new List<KPIViewModel>();
            using (SqlConnection conn = new SqlConnection(conns))
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                {
                    if (conn.State == System.Data.ConnectionState.Closed)
                        conn.Open();
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.Add("@START_DATE", "2013-09-30");
                    cmd.Parameters.Add("@EMPID", "A1083");
                    cmd.Parameters.Add("@type", "N");
                    cmd.Parameters.Add("@END_DATE", "2013-10-30");
                    using (SqlDataReader dr = cmd.ExecuteReader())
                    {
                        if (dr.HasRows)
                        {
                            while (dr.Read())
                            {
                                KPIViewModel _KPIViewModel = new KPIViewModel 
                                {
                                    KPI_FCODE = dr["KPI_FCODE"].ToString(),
                                    KPI_FNAME = dr["KPI_FNAME"].ToString(),
                                    KPI_M_code = dr["KPI_M_code"].ToString(),
                                    KPI_M_name = dr["KPI_M_name"].ToString(),
                                    KPI_M_weight = dr["KPI_M_weight"].ToString(),
                                    KPI_D_code = dr["KPI_D_code"].ToString(),
                                    KPI_D_name = dr["KPI_D_name"].ToString(),
                                    KPI_D_weight = dr["KPI_D_weight"].ToString(),
                                    KPI_SUBD_Name = dr["KPI_SUBD_Name"].ToString(),
                                    KPI_SUBDESC_Name = dr["KPI_SUBDESC_Name"].ToString(),
                                    POINT_EMP = dr["POINT_EMP"].ToString(),
                                    KPI_DESC = dr["KPI_DESC"].ToString(),
                                    POINT_LEADER2 = dr["POINT_LEADER2"].ToString(),
                                    POINT_LEADER3 = dr["POINT_LEADER3"].ToString(),
                                    PointASerial = int.Parse(dr["PointASerial"].ToString()),
                                    PointBSerial = int.Parse(dr["PointBSerial"].ToString()),
                                    PointCSerial = int.Parse(dr["PointCSerial"].ToString())
                                };
                                kpis.Add(_KPIViewModel);
                            }
                            srcvmode.kpis = kpis.AsEnumerable();
                        }
                    }
                }
            }
            sw.Stop();
            srcvmode.costtime = sw.ElapsedMilliseconds.ToString();
            return srcvmode;

        }

 


private IndexBViewModel Async(IndexBViewModel srcvmode)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Reset();
            sw.Start();
            var t0 = Task.Factory.StartNew(() =>
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                string sqlstatement = @"select * from COMPANY";
                using (SqlConnection conn = new SqlConnection(conns))
                {
                    using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                    {
                        if (conn.State == System.Data.ConnectionState.Closed)
                            conn.Open();
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            if (dr.HasRows)
                            {
                                while (dr.Read())
                                {
                                    ddls.Add(new SelectListItem
                                    {
                                        Text = dr["name"].ToString(),
                                        Value = dr["id"].ToString()
                                    });
                                }
                                srcvmode.companys = ddls.AsEnumerable();
                            }
                        }
                    }
                }
            });

            var t1 = Task.Factory.StartNew(() =>
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                string sqlstatement = @"select * from TITLE";
                using (SqlConnection conn = new SqlConnection(conns))
                {
                    using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                    {
                        if (conn.State == System.Data.ConnectionState.Closed)
                            conn.Open();
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            if (dr.HasRows)
                            {
                                while (dr.Read())
                                {
                                    ddls.Add(new SelectListItem
                                    {
                                        Text = dr["name"].ToString(),
                                        Value = dr["id"].ToString()
                                    });
                                }
                                srcvmode.titles = ddls.AsEnumerable();
                            }
                        }
                    }
                }
            });

            var t2 = Task.Factory.StartNew(() =>
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                string sqlstatement = @"select * from BRANCH";
                using (SqlConnection conn = new SqlConnection(conns))
                {
                    using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                    {
                        if (conn.State == System.Data.ConnectionState.Closed)
                            conn.Open();
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            if (dr.HasRows)
                            {
                                while (dr.Read())
                                {
                                    ddls.Add(new SelectListItem
                                    {
                                        Text = dr["name"].ToString(),
                                        Value = dr["id"].ToString()
                                    });
                                }
                                srcvmode.branchs = ddls.AsEnumerable();
                            }
                        }
                    }
                }
            });

            var t3 = Task.Factory.StartNew(() =>
            {
                List<SelectListItem> ddls = new List<SelectListItem>();
                string sqlstatement = @"select * from DEPARTMENT";
                using (SqlConnection conn = new SqlConnection(conns))
                {
                    using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                    {
                        if (conn.State == System.Data.ConnectionState.Closed)
                            conn.Open();
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            if (dr.HasRows)
                            {
                                while (dr.Read())
                                {
                                    ddls.Add(new SelectListItem
                                    {
                                        Text = dr["name"].ToString(),
                                        Value = dr["id"].ToString()
                                    });
                                }
                                srcvmode.departs = ddls.AsEnumerable();
                            }

                        }
                    }
                }
            });
            var t4 = Task.Factory.StartNew(() => 
            {
                string sqlstatement = @"USP_GetGetKPIFormData";
                List<KPIViewModel> kpis = new List<KPIViewModel>();
                using (SqlConnection conn = new SqlConnection(conns))
                {
                    List<SelectListItem> ddls = new List<SelectListItem>();
                    using (SqlCommand cmd = new SqlCommand(sqlstatement, conn))
                    {
                        if (conn.State == System.Data.ConnectionState.Closed)
                            conn.Open();
                        cmd.CommandType = CommandType.StoredProcedure;
                        cmd.Parameters.Add("@START_DATE", "2013-09-30");
                        cmd.Parameters.Add("@EMPID", "A1083");
                        cmd.Parameters.Add("@type", "N");
                        cmd.Parameters.Add("@END_DATE", "2013-10-30");
                        using (SqlDataReader dr = cmd.ExecuteReader())
                        {
                            if (dr.HasRows)
                            {
                                while (dr.Read())
                                {
                                    KPIViewModel _KPIViewModel = new KPIViewModel
                                    {
                                        KPI_FCODE = dr["KPI_FCODE"].ToString(),
                                        KPI_FNAME = dr["KPI_FNAME"].ToString(),
                                        KPI_M_code = dr["KPI_M_code"].ToString(),
                                        KPI_M_name = dr["KPI_M_name"].ToString(),
                                        KPI_M_weight = dr["KPI_M_weight"].ToString(),
                                        KPI_D_code = dr["KPI_D_code"].ToString(),
                                        KPI_D_name = dr["KPI_D_name"].ToString(),
                                        KPI_D_weight = dr["KPI_D_weight"].ToString(),
                                        KPI_SUBD_Name = dr["KPI_SUBD_Name"].ToString(),
                                        KPI_SUBDESC_Name = dr["KPI_SUBDESC_Name"].ToString(),
                                        POINT_EMP = dr["POINT_EMP"].ToString(),
                                        KPI_DESC = dr["KPI_DESC"].ToString(),
                                        POINT_LEADER2 = dr["POINT_LEADER2"].ToString(),
                                        POINT_LEADER3 = dr["POINT_LEADER3"].ToString(),
                                        PointASerial = int.Parse(dr["PointASerial"].ToString()),
                                        PointBSerial = int.Parse(dr["PointBSerial"].ToString()),
                                        PointCSerial = int.Parse(dr["PointCSerial"].ToString())
                                    };
                                    kpis.Add(_KPIViewModel);
                                }
                                srcvmode.kpis = kpis.AsEnumerable();
                            }
                        }
                    }
                }
            });
            Task.WaitAll(new[] { t0, t1, t2, t3,t4 });
            sw.Stop();
            srcvmode.costtime = sw.ElapsedMilliseconds.ToString();
            return srcvmode;
        }

 

非同步執行5次平均花費時間(ms):24

image

 

同步執行5次平均花費時間(ms):37

image