- 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