2015年12月21日 星期一

[RWD][w3school+MVC]建立grid - 完整程式碼

layout:
<!DOCTYPE html>
<html>
<head>
    
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
    @RenderBody()
</body>
</html>
Controller:
private AdventureWorksEntities db = new AdventureWorksEntities();
 
        public ActionResult Grid()
        {
            var contacts = db.Contact.Take(50);
            return View(contacts.ToList());
        }
View:
 <style type="text/css">
    .container-fluid {
        margin5px;
    }
 
    div.row > div {
        border1px solid;
    }
 
    /*幾乎萬用型的消除grid重疊格線的css寫法(僅ie會失敗)*/
    /*這是將每一個row重複部分的border變成不重複的寫法,參考這個*/
    /* http://stackoverflow.com/questions/33810312/using-borders-on-column-divs-in-bootstrap */
    /*但是看半天網路上的文章,還是不懂文章的解釋,我個人的理解是:只要div的上面或是左邊有鄰居element,就會被他吸過去1px,因此造成border重疊的情況...*/
    /*ie:85%以上重複的線條消除,沒消除的大概就是ie的bug*/
    /*chrome:成功!*/
    /*iphone 6 plus:成功!*/
    /*Samsung S4:成功!*/
    div.row div {
        margin-top-1px;
        margin-left-1px;
    }
 
 
 
 
    @@media only screen and (max-width: 768px) {
        /*瀏覽器寬度小於768px的時候,會套用這個css*/
        .container-fluid .row:nth-child(even) {
            background-color#dcdcdc;
        }
 
        .container-fluid .row:nth-child(odd) {
            background-color#f0f0f0;
        }
    }
 
    @@media screen and (min-width: 768px) {
        /*瀏覽器寬度大於768px的時候,會套用這個css*/
        .container-fluid .row:nth-child(even) {
            background-color#dcdcdc;
        }
 
        .container-fluid .row:nth-child(odd) {
            background-color#f0f0f0;
        }
    }
</style>
 
@model IEnumerable<RWDMVC.Models.Contact>
 
@{
    ViewBag.Title = "TestGrid";
}
 
<div class="container-fluid">
    <h1>RWD Grid Test</h1>
    <p>根據瀏覽器寬度調整grid的樣式</p>
 
    @if (Model.Count() > 0)
    {
 
        <div class="row" style="background-color#c1eafftext-aligncenter;">
            <div class="col-sm-4 col-md-3 col-lg-2">ContactName</div>
            <div class="col-sm-4 col-md-3 col-lg-2">Phone</div>
            <div class="col-sm-4 col-md-6 col-lg-8">EmailAddress</div>
          
        </div>
        foreach (var item in Model)
        {
 
            <div class="row">
                <div class="col-sm-4 col-md-3 col-lg-2">@Html.DisplayFor(modelItem => item.LastName) @Html.DisplayFor(modelItem => item.FirstName)</div>
                <div class="col-sm-4 col-md-3 col-lg-2">@Html.DisplayFor(modelItem => item.Phone)</div>
                <div class="col-sm-4 col-md-6 col-lg-8">@Html.DisplayFor(modelItem => item.EmailAddress)</div>
               
            </div>
        }
 
 
    }
 
</div>

...
...

2015年12月8日 星期二

[參考程式碼][WebService]最佳化呼叫WebService的頻率(wcf版本)

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Threading.Tasks;

namespace TPEPublicValuePriceCaller
{
    // 注意: 您可以使用 [重構] 功能表上的 [重新命名] 命令同時變更程式碼、svc 和組態檔中的類別名稱 "Service1"。
    // 注意: 若要啟動 WCF 測試用戶端以便測試此服務,請在 [方案總管] 中選取 Service1.svc 或 Service1.svc.cs,然後開始偵錯。
    public class Service : IService
    {
        #region 宣告變數
        //估計執行總時間:
        Stopwatch watch = new Stopwatch();
        //用來避免重複執行start的
        DateTime myUpdateDate;

        //臺北市的timer
        System.Timers.Timer tpeQueryTPETimer = new System.Timers.Timer();
        System.Timers.Timer tpeAvgSpeedTimer = new System.Timers.Timer();


        //新北市的timer

        System.Timers.Timer newTpeQueryTPETimer = new System.Timers.Timer();
        System.Timers.Timer newTpeAvgSpeedTimer = new System.Timers.Timer();


        bool tpeWCFCalling = false;
        bool newTpeWCFCalling = false;


        //臺北市的狀態記錄
        int tpeNowCount;//現在執行完畢的筆數
        int tpeOldCount;//五秒前的執行完畢的筆數   
        int tpeTotalCount;//臺北市總筆數

        //新北市的狀態記錄
        int newTpeNowCount;//現在執行完畢的筆數
        int newTpeOldCount;//五秒前的執行完畢的筆數   
        int newTpeTotalCount;//新北市總筆數

        //臺北市的平均執行速度狀態記錄
        int tpeOldMinuteCount; //一分鐘前執行完畢的筆數
        int tpeNowMinuteCount; //目前執行完畢的筆數        

        //新北市的平均執行速度狀態記錄
        int newTpeOldMinuteCount; //一分鐘前執行完畢的筆數
        int newTpeNowMinuteCount; //目前執行完畢的筆數

        string tpeCityCode = "0000"; //臺北市城市代碼        
        string newTpeCityCode = "0001";//新北市程式代碼
        #endregion

        #region operation contract
        public string StartBatchExe()
        {
            string serverStatus = "未知的狀態,請恰系統管理員!";

            //檢查是否有其他伺服器正在發送
            string yOrN = "";
            string ip = "";
            using (RobotEntities dbRobot = new RobotEntities())
            {
                //同一時間只能有一個instance執行大量發送
                var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
                yOrN = exeSetup.CODE_VALUE.Trim();
                ip = exeSetup.CODE_MEMO.Trim();
            }

            if (yOrN == "N" && ip == "")
            {
                //表示沒其他主機再發送,因此可以繼續執行
                //並記錄目前發送中的ip                    
                //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行
                UpdateExeSetup("Y", GetHostIP());
                serverStatus = "批次執行成功!";
            }
            else
            {
                //已經有其他台主機再發送,或是自己這台已經再發送
                //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行
                UpdateExeSetup("Y", GetHostIP());
                serverStatus = "批次執行成功!(已強制其他執行中的instance終止執行)";

            }


            init();

            //開始記錄總執行時間
            watch.Start();

            //開始查詢臺北
            TPETimerStart();
            tpeNowCount = GetTpeFinCountNow();
            tpeOldCount = tpeNowCount;
            tpeNowMinuteCount = tpeNowCount;
            tpeOldMinuteCount = tpeNowCount;

            //開始查詢新北
            NewTPETimerStart();
            newTpeNowCount = GetNewTpeFinCountNow();
            newTpeOldCount = newTpeNowCount;
            newTpeNowMinuteCount = newTpeNowCount;
            newTpeOldMinuteCount = newTpeNowCount;



            return serverStatus;
        }
        public string StopBatchExe()
        {
            string serverStatus = "未知的狀態,請恰系統管理員!";
            //將目前執行中的主機設定為空字串            
            UpdateExeSetup("N", "");
            serverStatus = "已成功停止執行!";
            return serverStatus;
        }
        #endregion
        
        #region 其他 methods
        private void init()
        {
            //初始化筆數
            using (rehouseEntities db = new rehouseEntities())
            {
                //臺北市總筆數  
                tpeTotalCount = db.pft23.Where(p => p.city_code == tpeCityCode).Count();

                //新北市總筆數
                newTpeTotalCount = db.pft23.Where(p => p.city_code == newTpeCityCode).Count();


            }

            //為timer設定事件
            //臺北市

            tpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢            
            this.tpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(tpeQueryTPETimer_Tick);
            tpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
            tpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryTPEAverageSpeed_Tick);

            //新北市

            newTpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
            newTpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(newTpeQueryTPETimer_Tick);
            newTpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
            newTpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryNewTPEAverageSpeed_Tick);

        }

        public string GetHostIP()
        {

            var result = string.Empty;

            // 取得本機名稱
            var strHostName = Dns.GetHostName();

            // 取得本機的 IpHostEntry 類別實體
            var iphostentry = Dns.GetHostEntry(strHostName);

            var ipv4 = iphostentry.AddressList.Where((e) => e.AddressFamily.ToString().Equals("InterNetwork")).ToList();

            if (ipv4.Any())
            {
                result = ipv4.First().ToString().Trim();
            }

            return result;

        }

        /// 
        /// 更新目前執行狀態
        /// 
        /// 
        /// 
        private void UpdateExeSetup(string yOrN, string ip)
        {
            using (RobotEntities dbRobot = new RobotEntities())
            {
                var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
                exeSetup.CODE_VALUE = yOrN;
                exeSetup.CODE_MEMO = ip;
                //資料庫型態開DateTime的話,millisecond精準度需用SqlDateTime轉換為sqlserver專用的,不然會差個0.00X毫秒
                myUpdateDate = new SqlDateTime(DateTime.Now).Value;
                exeSetup.Update_Date = new SqlDateTime(myUpdateDate).Value;
                dbRobot.SaveChanges();
            }
        }
       
        #endregion

        #region Timer 委派事件

        //每3秒持續呼叫臺北wcf一次
        private void tpeQueryTPETimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (TimerCheckIfExe() == false)
            {
                return;
            }

            tpeNowCount = GetTpeFinCountNow();//現在執行完畢的筆數
            //尚未達到總筆數的時候
            if (tpeNowCount != tpeTotalCount)
            {
                //等上次呼叫的兩百筆執行完才繼續呼叫

                if (tpeNowCount == tpeOldCount
                    || tpeNowCount >= tpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
                    - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
                {
                    //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
                    //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
                    //呼叫之前,先記錄目前執行完畢的筆數
                    //如果正在呼叫中,就不要一直呼叫,不然iis會過載
                    if (tpeWCFCalling == false)
                    {
                        tpeOldCount = GetTpeFinCountNow();
                        tpeWCFCalling = true;
                        //Task.Run(() => QueryTPEByService());
                        Task.Factory.StartNew(() => QueryTPEByService());
                    }
                }
                else if (tpeNowCount < tpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
                {
                    //還沒執行完上次呼叫的兩百筆,什麼都不做
                }
                else
                {
                    //

                }

            }
            else
            {
                //已經到達總筆數
                StopTpeTimer();
                //如果新北市也已經查完了,就紀錄目前無伺服器在大量發送wcf                
                if (newTpeTotalCount == GetNewTpeFinCountNow())
                {
                    //將目前執行中的主機設定為空字串
                    UpdateExeSetup("N", "");
                }
            }


        }

        //確認每分鐘臺北查詢速度
        private void queryTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e)
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                tpeNowMinuteCount = GetTpeFinCountNow();

                //每三分鐘檢查一次是否速度降為零
                //是的話,就重送
                if (DateTime.Now.Minute % 3 == 0 && tpeNowCount != tpeTotalCount)
                {
                    if (tpeNowMinuteCount - tpeOldMinuteCount == 0)
                    {
                        tpeOldCount = tpeNowCount;
                    }
                }

                tpeOldMinuteCount = GetTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
            }
        }

        //每五秒持續呼叫新北wcf一次
        private void newTpeQueryTPETimer_Tick(object sender, EventArgs e)
        {

            if (TimerCheckIfExe() == false)
            {
                return;
            }

            newTpeNowCount = GetNewTpeFinCountNow();//現在執行完畢的筆數
            //尚未達到總筆數的時候
            if (newTpeNowCount != newTpeTotalCount)
            {
                //等上次呼叫的兩百筆執行完才繼續呼叫
                if (newTpeNowCount == newTpeOldCount
                    || newTpeNowCount >= newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
                    - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
                {
                    //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
                    //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
                    //呼叫之前,先記錄目前執行完畢的筆數
                    //如果正在呼叫中,就不要一直呼叫,不然iis會過載
                    if (newTpeWCFCalling == false)
                    {
                        newTpeOldCount = GetNewTpeFinCountNow();
                        newTpeWCFCalling = true;
                        //Task.Run(() => QueryNewTPEByService());
                        Task.Factory.StartNew(() => QueryNewTPEByService());
                    }
                }
                else if (newTpeNowCount < newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
                {
                    //還沒執行完上次呼叫的兩百筆,什麼都不做
                }
                else
                {
                    //

                }

            }
            else
            {
                //已經到達總筆數                
                StopNewTpeTimer();
                //如果臺北市也已經查完了,就紀錄目前無伺服器在大量發送wcf                
                if (tpeTotalCount == GetTpeFinCountNow())
                {
                    //將目前執行中的主機設定為空字串
                    UpdateExeSetup("N", "");
                }
            }


        }

        //確認每分鐘新北查詢速度
        private void queryNewTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e)
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                newTpeNowMinuteCount = GetNewTpeFinCountNow();
                string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(newTpeNowMinuteCount - newTpeOldMinuteCount);

                //每三分鐘檢查一次是否速度降為零
                //是的話,就重送
                if (DateTime.Now.Minute % 3 == 0 && newTpeNowCount != newTpeTotalCount)
                {
                    //如果新北市官網的回應太少導致ResponseRate太低導致該分鐘的速度為0的話,就再度重送
                    if (newTpeNowMinuteCount - newTpeOldMinuteCount == 0)
                    {
                        newTpeOldCount = newTpeNowCount;
                    }
                }


                newTpeOldMinuteCount = GetNewTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
            }
        }

        


        #endregion

        #region timer method

        /// 
        /// timer週期性的檢查是否可以繼續執行
        /// 
        /// 
        private bool TimerCheckIfExe()
        {
            bool result = false;

            //檢查是否被中斷
            string yOrN = "";
            string ip = "";
            DateTime updateDate;
            using (RobotEntities dbRobot = new RobotEntities())
            {
                //同一時間只能有一個instance執行大量發送
                var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
                yOrN = exeSetup.CODE_VALUE.Trim();
                ip = exeSetup.CODE_MEMO.Trim();
                updateDate = exeSetup.Update_Date;
            }
            //依照db裡面的yOrN+ip+updateDate,來判斷是否多個instance重複執行
            if (yOrN == "Y" && ip == GetHostIP() && myUpdateDate == updateDate)
            {
                //可以繼續執行
                result = true;
            }
            else
            {
                //可能是 Y + 其他ip正在執行
                //可能是 N + empty
                //以上狀況都要終止執行
                //參數設定可能已經由其他instance取代,因此便不再執行UpdateExeSetup();
                StopTpeTimer();
                StopNewTpeTimer();
                result = false;
            }



            //執行超過八小時一樣強制結束
            if (watch.Elapsed.TotalHours > 8)
            {
                watch.Stop();
                StopTpeTimer();
                StopNewTpeTimer();
                UpdateExeSetup("N", "");
                result = false;
            }

            return result;
        }

        //啟動臺北timer
        private void TPETimerStart()
        {
            tpeQueryTPETimer.Start();
            tpeAvgSpeedTimer.Start();

        }

        //啟動新北timer
        private void NewTPETimerStart()
        {
            newTpeQueryTPETimer.Start();
            newTpeAvgSpeedTimer.Start();

        }

        private void StopTpeTimer()
        {
            tpeQueryTPETimer.Stop();
            tpeAvgSpeedTimer.Stop();


        }

        private void StopNewTpeTimer()
        {
            newTpeQueryTPETimer.Stop();
            newTpeAvgSpeedTimer.Stop();

        }

        #endregion

        #region 檢查目前查詢進度method

        //取得臺北目前查詢完畢的資料筆數
        private int GetTpeFinCountNow()
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == tpeCityCode).Count();
            }
        }

        //取得新北目前查詢完畢的資料筆數
        private int GetNewTpeFinCountNow()
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == newTpeCityCode).Count();
            }
        }

        #endregion

        #region 呼叫WCF查詢臺北市、新北市

        //呼叫wcf查詢臺北
        private void QueryTPEByService()
        {

            TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
            using (rehouseEntities db = new rehouseEntities())
            {
                var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == tpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
                foreach (var p23 in pft23s)
                {
                    sc.GetTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
                }

            }
            sc.Close();
            tpeWCFCalling = false;//呼叫完畢
        }

        //呼叫wcf查詢臺北
        private void QueryNewTPEByService()
        {
            TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
            using (rehouseEntities db = new rehouseEntities())
            {
                var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == newTpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
                foreach (var p23 in pft23s)
                {
                    sc.GetNewTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
                }

            }
            sc.Close();
            newTpeWCFCalling = false;//呼叫完畢
        }

        #endregion
    }
}
參數設定的部分參考winform的完整程式碼即可囉:
http://saltsourcecenter.blogspot.tw/2015/11/webservicewebservice.html

2015年11月23日 星期一

[參考程式碼][WebService]最佳化呼叫WebService的頻率(Winform版本)

Form的外觀:

Form1.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace TPEPublicValuePriceWinForm
{
    public partial class Form1 : Form
    {
        //臺北市的timer
        System.Windows.Forms.Timer tpeProgrssBarTimer = new System.Windows.Forms.Timer();
        System.Windows.Forms.Timer tpeQueryTPETimer = new System.Windows.Forms.Timer();
        System.Windows.Forms.Timer tpeAvgSpeedTimer = new System.Windows.Forms.Timer();
        

        //新北市的timer
        System.Windows.Forms.Timer newTpeProgrssBarTimer = new System.Windows.Forms.Timer();
        System.Windows.Forms.Timer newTpeQueryTPETimer = new System.Windows.Forms.Timer();
        System.Windows.Forms.Timer newTpeAvgSpeedTimer = new System.Windows.Forms.Timer();
        

        bool tpeWCFCalling = false;
        bool newTpeWCFCalling = false;


        //臺北市的狀態記錄
        int tpeNowCount;//現在執行完畢的筆數
        int tpeOldCount;//五秒前的執行完畢的筆數   
        int tpeTotalCount;//臺北市總筆數

        //新北市的狀態記錄
        int newTpeNowCount;//現在執行完畢的筆數
        int newTpeOldCount;//五秒前的執行完畢的筆數   
        int newTpeTotalCount;//新北市總筆數

        //臺北市的平均執行速度狀態記錄
        int tpeOldMinuteCount; //一分鐘前執行完畢的筆數
        int tpeNowMinuteCount; //目前執行完畢的筆數        

        //新北市的平均執行速度狀態記錄
        int newTpeOldMinuteCount; //一分鐘前執行完畢的筆數
        int newTpeNowMinuteCount; //目前執行完畢的筆數

        string tpeCityCode = "0000"; //臺北市城市代碼        
        string newTpeCityCode = "0001";//新北市程式代碼



        public Form1()
        {

            InitializeComponent();
            init();

        }

        private void init()
        {
            //初始化筆數
            using (rehouseEntities db = new rehouseEntities())
            {
                //臺北市總筆數
                TPETotalCountLbl.Text = db.pft23.Where(p => p.city_code == tpeCityCode).Count().ToString();
                tpeTotalCount = Convert.ToInt32(TPETotalCountLbl.Text);
                //臺北市執行完畢筆數                
                TPEFinCountLbl.Text = GetTpeFinCountNow().ToString();

                //新北市總筆數
                NewTPETotalCountLbl.Text = db.pft23.Where(p => p.city_code == newTpeCityCode).Count().ToString();
                newTpeTotalCount = Convert.ToInt32(NewTPETotalCountLbl.Text);
                //新北市執行完畢筆數                
                NewTPEFinCountLbl.Text = GetNewTpeFinCountNow().ToString();

            }

            //為timer設定事件
            //臺北市
            tpeProgrssBarTimer.Interval = Convert.ToInt16(Config.ProgressBarCheckTime);//3 secs顯示一次進度
            tpeProgrssBarTimer.Tick += new System.EventHandler(tpeProgrssBarTimer_Tick);
            tpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
            tpeQueryTPETimer.Tick += new System.EventHandler(tpeQueryTPETimer_Tick);
            tpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
            tpeAvgSpeedTimer.Tick += new System.EventHandler(queryTPEAverageSpeed_Tick);
            
            //新北市
            newTpeProgrssBarTimer.Interval = Convert.ToInt16(Config.ProgressBarCheckTime);//3 secs顯示一次進度
            newTpeProgrssBarTimer.Tick += new System.EventHandler(newTpeProgrssBarTimer_Tick);
            newTpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
            newTpeQueryTPETimer.Tick += new System.EventHandler(newTpeQueryTPETimer_Tick);
            newTpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
            newTpeAvgSpeedTimer.Tick += new System.EventHandler(queryNewTPEAverageSpeed_Tick);
            
        }

        #region control event

        //按下查詢臺北
        private void QueryTPEBtn_Click(object sender, EventArgs e)
        {            
            TPETimerStart();            
            exeTPEStatusLbl.Text = "執行中";            
            exeTPEStatusLbl.Text = "執行中";
            tpeNowCount = GetTpeFinCountNow();
            tpeOldCount = tpeNowCount;
            tpeNowMinuteCount = tpeNowCount;                                          
            tpeOldMinuteCount = tpeNowCount;
            MessageBox.Show("已開始查詢臺北!");
        }

        //停止查詢臺北
        private void stopTPEBtn_Click(object sender, EventArgs e)
        {
            tpeProgrssBarTimer.Stop();
            tpeQueryTPETimer.Stop();
            tpeAvgSpeedTimer.Stop();
            exeTPEStatusLbl.Text = "停止";
            MessageBox.Show("已停止查詢臺北!");
        }

        //按下查詢新北
        private void QueryNewTPEBtn_Click(object sender, EventArgs e)
        {            
     
            NewTPETimerStart();
            exeNewTPEStatusLbl.Text = "執行中";                        

            exeNewTPEStatusLbl.Text = "執行中";
            newTpeNowCount = GetNewTpeFinCountNow();
            newTpeOldCount = newTpeNowCount;
            newTpeNowMinuteCount = newTpeNowCount;                                           
            newTpeOldMinuteCount = newTpeNowCount;
            MessageBox.Show("已開始查詢新北!");
        }

        //停止查詢新北
        private void stopNewTPEBtn_Click(object sender, EventArgs e)
        {
            newTpeProgrssBarTimer.Stop();
            newTpeQueryTPETimer.Stop();
            newTpeAvgSpeedTimer.Stop();
            exeNewTPEStatusLbl.Text = "停止";
            MessageBox.Show("已停止查詢新北!");
        }


        #endregion

        #region Timer Event
        //持續更新畫面上查詢臺北的進度
        private void tpeProgrssBarTimer_Tick(object sender, EventArgs e)
        {

            TPEFinCountLbl.Text = GetTpeFinCountNow().ToString();
            int temp = DateTime.Now.Millisecond % 3;
            if(temp ==0)
            {
                exeTPEStatusLbl.Text = "執行中。。。。。。";
            }
            else if (temp == 1)
            {
                exeTPEStatusLbl.Text = "執行中。。。。";
            }
            else if (temp == 2)
            {
                exeTPEStatusLbl.Text = "執行中。。";
            }
            
        }

        //每3秒持續呼叫臺北wcf一次
        private void tpeQueryTPETimer_Tick(object sender, EventArgs e)
        {
            
            tpeNowCount = GetTpeFinCountNow();//現在執行完畢的筆數
            //尚未達到總筆數的時候
            if (tpeNowCount != tpeTotalCount)
            {
                //等上次呼叫的兩百筆執行完才繼續呼叫

                if (tpeNowCount == tpeOldCount
                    || tpeNowCount >= tpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
                    - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
                {
                    //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
                    //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
                    //呼叫之前,先記錄目前執行完畢的筆數
                    //如果正在呼叫中,就不要一直呼叫,不然iis會過載
                    if (tpeWCFCalling == false)
                    {
                        tpeOldCount = GetTpeFinCountNow();
                        tpeWCFCalling = true;
                        Task.Run(() => QueryTPEByService());
                    }
                }
                else if(tpeNowCount < tpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
                {
                    //還沒執行完上次呼叫的兩百筆,什麼都不做
                }
                else
                {
                    //
                    
                }

            }
            else
            {
                //已經到達總筆數
                TPEFinCountLbl.Text = tpeNowCount.ToString();
                exeTPEStatusLbl.Text = "已執行完畢!";
                StopTpeTimer();
            }

            
        }

        //確認每分鐘臺北查詢速度
        private void queryTPEAverageSpeed_Tick(object sender, EventArgs e)
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                tpeNowMinuteCount = GetTpeFinCountNow();
                string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(tpeNowMinuteCount - tpeOldMinuteCount);
                TPEAvgSpeedTxt.Text = TPEAvgSpeedTxt.Text + avgSpeedResult + "\r\n";
                //每三分鐘檢查一次是否速度降為零
                //是的話,就重送
                if (DateTime.Now.Minute % 3 == 0 && tpeNowCount != tpeTotalCount)
                {
                    if (tpeNowMinuteCount - tpeOldMinuteCount == 0)
                    {
                        tpeOldCount = tpeNowCount;
                    }
                }
         
                tpeOldMinuteCount = GetTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
            }
        }

       

        //持續更新畫面上查詢新北的進度
        private void newTpeProgrssBarTimer_Tick(object sender, EventArgs e)
        {

            NewTPEFinCountLbl.Text = GetNewTpeFinCountNow().ToString();
            int temp = DateTime.Now.Millisecond % 3;
            if (temp == 0)
            {
                exeNewTPEStatusLbl.Text = "執行中。。";
            }
            else if (temp == 1)
            {
                exeNewTPEStatusLbl.Text = "執行中。。。。。。";
            }
            else if (temp == 2)
            {
                exeNewTPEStatusLbl.Text = "執行中。。。。";
            }
            
        }

        //每五秒持續呼叫新北wcf一次
        private void newTpeQueryTPETimer_Tick(object sender, EventArgs e)
        {
           

            newTpeNowCount = GetNewTpeFinCountNow();//現在執行完畢的筆數
            //尚未達到總筆數的時候
            if (newTpeNowCount != newTpeTotalCount)
            {
                //等上次呼叫的兩百筆執行完才繼續呼叫
                if (newTpeNowCount == newTpeOldCount
                    || newTpeNowCount >= newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
                    - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
                {
                    //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
                    //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
                    //呼叫之前,先記錄目前執行完畢的筆數
                    //如果正在呼叫中,就不要一直呼叫,不然iis會過載
                    if (newTpeWCFCalling == false)
                    {
                        newTpeOldCount = GetNewTpeFinCountNow();
                        newTpeWCFCalling = true;
                        Task.Run(() => QueryNewTPEByService());
                    }
                }
                else if (newTpeNowCount < newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
                {
                    //還沒執行完上次呼叫的兩百筆,什麼都不做
                }
                else
                {
                    //

                }

            }
            else
            {
                //已經到達總筆數
                NewTPEFinCountLbl.Text = newTpeNowCount.ToString();
                exeNewTPEStatusLbl.Text = "已執行完畢!";
                StopNewTpeTimer();
            }


        }

        //確認每分鐘新北查詢速度
        private void queryNewTPEAverageSpeed_Tick(object sender, EventArgs e)
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                newTpeNowMinuteCount = GetNewTpeFinCountNow();
                string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(newTpeNowMinuteCount - newTpeOldMinuteCount);
                NewTPEAvgSpeedTxt.Text = NewTPEAvgSpeedTxt.Text + avgSpeedResult + "\r\n";
                //每三分鐘檢查一次是否速度降為零
                //是的話,就重送
                if (DateTime.Now.Minute % 3 == 0 && newTpeNowCount != newTpeTotalCount)
                {
                    //如果新北市官網的回應太少導致ResponseRate太低導致該分鐘的速度為0的話,就再度重送
                    if (newTpeNowMinuteCount - newTpeOldMinuteCount == 0)
                    {
                        newTpeOldCount = newTpeNowCount;
                    }
                }
                

                newTpeOldMinuteCount = GetNewTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
            }
        }

        private void StopTpeTimer()
        {
            tpeProgrssBarTimer.Stop();
            tpeQueryTPETimer.Stop();
            tpeAvgSpeedTimer.Stop();
     
        }

        private void StopNewTpeTimer()
        {
            newTpeProgrssBarTimer.Stop();
            newTpeQueryTPETimer.Stop();
            newTpeAvgSpeedTimer.Stop();
           
        }


        #endregion

        #region custom method

        //取得臺北目前查詢完畢的資料筆數
        private int GetTpeFinCountNow()
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == tpeCityCode).Count();
            }
        }

        //呼叫wcf查詢臺北
        private void QueryTPEByService()
        {

            TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
            using (rehouseEntities db = new rehouseEntities())
            {
                var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == tpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
                foreach (var p23 in pft23s)
                {
                    sc.GetTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
                }

            }
            sc.Close();
            tpeWCFCalling = false;//呼叫完畢
        }

        //啟動臺北timer
        private void TPETimerStart()
        {
            tpeProgrssBarTimer.Start();
            tpeQueryTPETimer.Start();
            tpeAvgSpeedTimer.Start();
    
        }

        //取得新北目前查詢完畢的資料筆數
        private int GetNewTpeFinCountNow()
        {
            using (rehouseEntities db = new rehouseEntities())
            {
                return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == newTpeCityCode).Count();
            }
        }

        //呼叫wcf查詢臺北
        private void QueryNewTPEByService()
        {
            TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
            using (rehouseEntities db = new rehouseEntities())
            {
                var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == newTpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
                foreach (var p23 in pft23s)
                {
                    sc.GetNewTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
                }

            }
            sc.Close();
            newTpeWCFCalling = false;//呼叫完畢
        }

        //啟動新北timer
        private void NewTPETimerStart()
        {
            newTpeProgrssBarTimer.Start();
            newTpeQueryTPETimer.Start();
            newTpeAvgSpeedTimer.Start();
        
        }
        #endregion


    }
}

Config.cs:方便快速存取appsetting用的類別
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;

namespace TPEPublicValuePriceWinForm
{
    public class Config
    {        
        public static string SleepTime = GetAppSettings("SleepTime");
        public static string ProgressBarCheckTime = GetAppSettings("ProgressBarCheckTime");
        public static string AverageSpeedCheckTime = GetAppSettings("AverageSpeedCheckTime");
        public static string ResponseLostTime = GetAppSettings("ResponseLostTime");
        
        public static string AutoStopCount = GetAppSettings("AutoStopCount");
        public static string AutoInitCount = GetAppSettings("AutoInitCount");
        public static string OnceTakeCount = GetAppSettings("OnceTakeCount");
        public static string NoResponseRate = GetAppSettings("NoResponseRate");

        private static string GetAppSettings(string key)
        {
            return  ConfigurationManager.AppSettings[key];
        }
    }
}


app.config檔裡面參考的參數:主要是設定timer每多少秒數要執行一次
<appSettings>  
<add key="SleepTime" value="3000"/>
<add key="ProgressBarCheckTime" value="3000"/>
<add key="AverageSpeedCheckTime" value="60000"/>
<add key="ResponseLostTime" value="150000"/>
<add key="AutoStopCount" value="10"/>
<add key="AutoInitCount" value="30"/>
<add key="OnceTakeCount" value="200"/>
<add key="NoResponseRate" value="0.1"/>

</appSettings>

2015年10月22日 星期四

ConfigureAwait.aspx

ConfigureAwait.aspx
<%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="ConfigureAwait.aspx.cs" Inherits="ConcurrencyWebForm.ConfigureAwait" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Button ID="btnSyncWithoutConfigureAwait" runat="server" Text="SyncWithoutConfigureAwait" OnClick="btnSyncWithoutConfigureAwait_Click" />
            <br />
            <asp:Button ID="btnSyncWithConfigureAwait" runat="server" Text="SyncWithConfigureAwait" OnClick="btnSyncWithConfigureAwait_Click" />
            <br />
            <asp:Button ID="btnAsyncWithConfigureAwait" runat="server" Text="AsyncWithConfigureAwait" OnClick="btnAsyncWithConfigureAwait_Click" />
        </div>
    </form>
</body>
</html>

ConfigureAwait.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ConcurrencyWebForm
{
    public partial class ConfigureAwait : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        
        //此例會造成Deadlock        
        //ps.以同步的方式執行非同步的function是非常不建議的
        protected void btnSyncWithoutConfigureAwait_Click(object sender, EventArgs e)
        {            
            Task tVal = DoSomethingAsync();
            string abc = "";
            string cde = "";
            Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + tVal.Result.ToString() + "');", true);
        }

        private async Task DoSomethingAsync()
        {
            int val = 13;

            // Asynchronously wait 3 second.
            //只是為了讓此library function為非同步執行才用Task.Delay,實際尚無特別意義
            await Task.Delay(TimeSpan.FromSeconds(3));

            val *= 2;

            // Asynchronously wait 3 second.
            await Task.Delay(TimeSpan.FromSeconds(3));
            
            return val;
        }



        protected void btnSyncWithConfigureAwait_Click(object sender, EventArgs e)
        {
            Task tVal = DoSomethingAsyncWithConfigureAwait();
            string abc = "";
            string cde = "";
            Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + tVal.Result.ToString() + "');", true);
        }

        //.ConfigureAwait(false)另開了context以儲存library function的執行狀態        
        private async Task DoSomethingAsyncWithConfigureAwait()
        {
            int val = 13;

            // Asynchronously wait 3 second.     
            //增加了.ConfigureAwait(false)另開了context
            await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);

            val *= 2;

            // Asynchronously wait 3 second.
            //增加了.ConfigureAwait(false)另開了context
            await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);

            return val;
        }

        protected async void btnAsyncWithConfigureAwait_Click(object sender, EventArgs e)
        {
            int intVal = await DoSomethingAsyncWithConfigureAwait();
            string abc = "";
            string cde = "";
            Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + intVal.ToString() + "');", true);
        }

      
    }
}