2015年12月21日 星期一

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

layout:
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     
  5.     <title>@ViewBag.Title - My ASP.NET Application</title>
  6.     <meta charset="utf-8">
  7.     <meta name="viewport" content="width=device-width, initial-scale=1">
  8.     <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  9.     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  10.     <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  11. </head>
  12. <body>
  13.     @RenderBody()
  14. </body>
  15. </html>
Controller:
  1. private AdventureWorksEntities db = new AdventureWorksEntities();
  2.         public ActionResult Grid()
  3.         {
  4.             var contacts = db.Contact.Take(50);
  5.             return View(contacts.ToList());
  6.         }
View:
  1.  <style type="text/css">
  2.  
  3.     .container-fluid {
  4.         margin: 5px;
  5.     }
  6.  
  7.     div.row > div {
  8.         border: 1px solid;
  9.     }
  10.  
  11.     /*幾乎萬用型的消除grid重疊格線的css寫法(僅ie會失敗)*/
  12.     /*這是將每一個row重複部分的border變成不重複的寫法,參考這個*/
  13.     /* http://stackoverflow.com/questions/33810312/using-borders-on-column-divs-in-bootstrap */
  14.     /*但是看半天網路上的文章,還是不懂文章的解釋,我個人的理解是:只要div的上面或是左邊有鄰居element,就會被他吸過去1px,因此造成border重疊的情況...*/
  15.     /*ie:85%以上重複的線條消除,沒消除的大概就是ie的bug*/
  16.     /*chrome:成功!*/
  17.     /*iphone 6 plus:成功!*/
  18.     /*Samsung S4:成功!*/
  19.     div.row div {
  20.         margin-top: -1px;
  21.         margin-left: -1px;
  22.     }
  23.  
  24.  
  25.  
  26.  
  27.     @@media only screen and (max-width: 768px) {
  28.         /*瀏覽器寬度小於768px的時候,會套用這個css*/
  29.         .container-fluid .row:nth-child(even) {
  30.             background-color: #dcdcdc;
  31.         }
  32.  
  33.         .container-fluid .row:nth-child(odd) {
  34.             background-color: #f0f0f0;
  35.         }
  36.     }
  37.  
  38.     @@media screen and (min-width: 768px) {
  39.         /*瀏覽器寬度大於768px的時候,會套用這個css*/
  40.         .container-fluid .row:nth-child(even) {
  41.             background-color: #dcdcdc;
  42.         }
  43.  
  44.         .container-fluid .row:nth-child(odd) {
  45.             background-color: #f0f0f0;
  46.         }
  47.     }
  48. </style>
  49.  
  50. @model IEnumerable<RWDMVC.Models.Contact>
  51.  
  52. @{
  53.     ViewBag.Title = "TestGrid";
  54. }
  55.  
  56. <div class="container-fluid">
  57.     <h1>RWD Grid Test</h1>
  58.     <p>根據瀏覽器寬度調整grid的樣式</p>
  59.  
  60.     @if (Model.Count() > 0)
  61.     {
  62.  
  63.         <div class="row" style="background-color: #c1eaff; text-align: center;">
  64.             <div class="col-sm-4 col-md-3 col-lg-2">ContactName</div>
  65.             <div class="col-sm-4 col-md-3 col-lg-2">Phone</div>
  66.             <div class="col-sm-4 col-md-6 col-lg-8">EmailAddress</div>
  67.           
  68.         </div>
  69.         foreach (var item in Model)
  70.         {
  71.  
  72.             <div class="row">
  73.                 <div class="col-sm-4 col-md-3 col-lg-2">@Html.DisplayFor(modelItem => item.LastName) @Html.DisplayFor(modelItem => item.FirstName)</div>
  74.                 <div class="col-sm-4 col-md-3 col-lg-2">@Html.DisplayFor(modelItem => item.Phone)</div>
  75.                 <div class="col-sm-4 col-md-6 col-lg-8">@Html.DisplayFor(modelItem => item.EmailAddress)</div>
  76.                
  77.             </div>
  78.         }
  79.  
  80.  
  81.     }
  82.  
  83. </div>
  84.  

...
...

2015年12月8日 星期二

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.SqlTypes;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Runtime.Serialization;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Web;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12.  
  13. namespace TPEPublicValuePriceCaller
  14. {
  15. // 注意: 您可以使用 [重構] 功能表上的 [重新命名] 命令同時變更程式碼、svc 和組態檔中的類別名稱 "Service1"。
  16. // 注意: 若要啟動 WCF 測試用戶端以便測試此服務,請在 [方案總管] 中選取 Service1.svc 或 Service1.svc.cs,然後開始偵錯。
  17. public class Service : IService
  18. {
  19. #region 宣告變數
  20. //估計執行總時間:
  21. Stopwatch watch = new Stopwatch();
  22. //用來避免重複執行start的
  23. DateTime myUpdateDate;
  24.  
  25. //臺北市的timer
  26. System.Timers.Timer tpeQueryTPETimer = new System.Timers.Timer();
  27. System.Timers.Timer tpeAvgSpeedTimer = new System.Timers.Timer();
  28.  
  29.  
  30. //新北市的timer
  31.  
  32. System.Timers.Timer newTpeQueryTPETimer = new System.Timers.Timer();
  33. System.Timers.Timer newTpeAvgSpeedTimer = new System.Timers.Timer();
  34.  
  35.  
  36. bool tpeWCFCalling = false;
  37. bool newTpeWCFCalling = false;
  38.  
  39.  
  40. //臺北市的狀態記錄
  41. int tpeNowCount;//現在執行完畢的筆數
  42. int tpeOldCount;//五秒前的執行完畢的筆數
  43. int tpeTotalCount;//臺北市總筆數
  44.  
  45. //新北市的狀態記錄
  46. int newTpeNowCount;//現在執行完畢的筆數
  47. int newTpeOldCount;//五秒前的執行完畢的筆數
  48. int newTpeTotalCount;//新北市總筆數
  49.  
  50. //臺北市的平均執行速度狀態記錄
  51. int tpeOldMinuteCount; //一分鐘前執行完畢的筆數
  52. int tpeNowMinuteCount; //目前執行完畢的筆數
  53.  
  54. //新北市的平均執行速度狀態記錄
  55. int newTpeOldMinuteCount; //一分鐘前執行完畢的筆數
  56. int newTpeNowMinuteCount; //目前執行完畢的筆數
  57.  
  58. string tpeCityCode = "0000"; //臺北市城市代碼
  59. string newTpeCityCode = "0001";//新北市程式代碼
  60. #endregion
  61.  
  62. #region operation contract
  63. public string StartBatchExe()
  64. {
  65. string serverStatus = "未知的狀態,請恰系統管理員!";
  66.  
  67. //檢查是否有其他伺服器正在發送
  68. string yOrN = "";
  69. string ip = "";
  70. using (RobotEntities dbRobot = new RobotEntities())
  71. {
  72. //同一時間只能有一個instance執行大量發送
  73. var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
  74. yOrN = exeSetup.CODE_VALUE.Trim();
  75. ip = exeSetup.CODE_MEMO.Trim();
  76. }
  77.  
  78. if (yOrN == "N" && ip == "")
  79. {
  80. //表示沒其他主機再發送,因此可以繼續執行
  81. //並記錄目前發送中的ip
  82. //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行
  83. UpdateExeSetup("Y", GetHostIP());
  84. serverStatus = "批次執行成功!";
  85. }
  86. else
  87. {
  88. //已經有其他台主機再發送,或是自己這台已經再發送
  89. //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行
  90. UpdateExeSetup("Y", GetHostIP());
  91. serverStatus = "批次執行成功!(已強制其他執行中的instance終止執行)";
  92.  
  93. }
  94.  
  95.  
  96. init();
  97.  
  98. //開始記錄總執行時間
  99. watch.Start();
  100.  
  101. //開始查詢臺北
  102. TPETimerStart();
  103. tpeNowCount = GetTpeFinCountNow();
  104. tpeOldCount = tpeNowCount;
  105. tpeNowMinuteCount = tpeNowCount;
  106. tpeOldMinuteCount = tpeNowCount;
  107.  
  108. //開始查詢新北
  109. NewTPETimerStart();
  110. newTpeNowCount = GetNewTpeFinCountNow();
  111. newTpeOldCount = newTpeNowCount;
  112. newTpeNowMinuteCount = newTpeNowCount;
  113. newTpeOldMinuteCount = newTpeNowCount;
  114.  
  115.  
  116.  
  117. return serverStatus;
  118. }
  119. public string StopBatchExe()
  120. {
  121. string serverStatus = "未知的狀態,請恰系統管理員!";
  122. //將目前執行中的主機設定為空字串
  123. UpdateExeSetup("N", "");
  124. serverStatus = "已成功停止執行!";
  125. return serverStatus;
  126. }
  127. #endregion
  128. #region 其他 methods
  129. private void init()
  130. {
  131. //初始化筆數
  132. using (rehouseEntities db = new rehouseEntities())
  133. {
  134. //臺北市總筆數
  135. tpeTotalCount = db.pft23.Where(p => p.city_code == tpeCityCode).Count();
  136.  
  137. //新北市總筆數
  138. newTpeTotalCount = db.pft23.Where(p => p.city_code == newTpeCityCode).Count();
  139.  
  140.  
  141. }
  142.  
  143. //為timer設定事件
  144. //臺北市
  145.  
  146. tpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
  147. this.tpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(tpeQueryTPETimer_Tick);
  148. tpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
  149. tpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryTPEAverageSpeed_Tick);
  150.  
  151. //新北市
  152.  
  153. newTpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
  154. newTpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(newTpeQueryTPETimer_Tick);
  155. newTpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
  156. newTpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryNewTPEAverageSpeed_Tick);
  157.  
  158. }
  159.  
  160. public string GetHostIP()
  161. {
  162.  
  163. var result = string.Empty;
  164.  
  165. // 取得本機名稱
  166. var strHostName = Dns.GetHostName();
  167.  
  168. // 取得本機的 IpHostEntry 類別實體
  169. var iphostentry = Dns.GetHostEntry(strHostName);
  170.  
  171. var ipv4 = iphostentry.AddressList.Where((e) => e.AddressFamily.ToString().Equals("InterNetwork")).ToList();
  172.  
  173. if (ipv4.Any())
  174. {
  175. result = ipv4.First().ToString().Trim();
  176. }
  177.  
  178. return result;
  179.  
  180. }
  181.  
  182. ///
  183. /// 更新目前執行狀態
  184. ///
  185. ///
  186. ///
  187. private void UpdateExeSetup(string yOrN, string ip)
  188. {
  189. using (RobotEntities dbRobot = new RobotEntities())
  190. {
  191. var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
  192. exeSetup.CODE_VALUE = yOrN;
  193. exeSetup.CODE_MEMO = ip;
  194. //資料庫型態開DateTime的話,millisecond精準度需用SqlDateTime轉換為sqlserver專用的,不然會差個0.00X毫秒
  195. myUpdateDate = new SqlDateTime(DateTime.Now).Value;
  196. exeSetup.Update_Date = new SqlDateTime(myUpdateDate).Value;
  197. dbRobot.SaveChanges();
  198. }
  199. }
  200. #endregion
  201.  
  202. #region Timer 委派事件
  203.  
  204. //每3秒持續呼叫臺北wcf一次
  205. private void tpeQueryTPETimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
  206. {
  207. if (TimerCheckIfExe() == false)
  208. {
  209. return;
  210. }
  211.  
  212. tpeNowCount = GetTpeFinCountNow();//現在執行完畢的筆數
  213. //尚未達到總筆數的時候
  214. if (tpeNowCount != tpeTotalCount)
  215. {
  216. //等上次呼叫的兩百筆執行完才繼續呼叫
  217.  
  218. if (tpeNowCount == tpeOldCount
  219. || tpeNowCount >= tpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
  220. - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
  221. {
  222. //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
  223. //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
  224. //呼叫之前,先記錄目前執行完畢的筆數
  225. //如果正在呼叫中,就不要一直呼叫,不然iis會過載
  226. if (tpeWCFCalling == false)
  227. {
  228. tpeOldCount = GetTpeFinCountNow();
  229. tpeWCFCalling = true;
  230. //Task.Run(() => QueryTPEByService());
  231. Task.Factory.StartNew(() => QueryTPEByService());
  232. }
  233. }
  234. else if (tpeNowCount < tpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
  235. {
  236. //還沒執行完上次呼叫的兩百筆,什麼都不做
  237. }
  238. else
  239. {
  240. //
  241.  
  242. }
  243.  
  244. }
  245. else
  246. {
  247. //已經到達總筆數
  248. StopTpeTimer();
  249. //如果新北市也已經查完了,就紀錄目前無伺服器在大量發送wcf
  250. if (newTpeTotalCount == GetNewTpeFinCountNow())
  251. {
  252. //將目前執行中的主機設定為空字串
  253. UpdateExeSetup("N", "");
  254. }
  255. }
  256.  
  257.  
  258. }
  259.  
  260. //確認每分鐘臺北查詢速度
  261. private void queryTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e)
  262. {
  263. using (rehouseEntities db = new rehouseEntities())
  264. {
  265. tpeNowMinuteCount = GetTpeFinCountNow();
  266.  
  267. //每三分鐘檢查一次是否速度降為零
  268. //是的話,就重送
  269. if (DateTime.Now.Minute % 3 == 0 && tpeNowCount != tpeTotalCount)
  270. {
  271. if (tpeNowMinuteCount - tpeOldMinuteCount == 0)
  272. {
  273. tpeOldCount = tpeNowCount;
  274. }
  275. }
  276.  
  277. tpeOldMinuteCount = GetTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
  278. }
  279. }
  280.  
  281. //每五秒持續呼叫新北wcf一次
  282. private void newTpeQueryTPETimer_Tick(object sender, EventArgs e)
  283. {
  284.  
  285. if (TimerCheckIfExe() == false)
  286. {
  287. return;
  288. }
  289.  
  290. newTpeNowCount = GetNewTpeFinCountNow();//現在執行完畢的筆數
  291. //尚未達到總筆數的時候
  292. if (newTpeNowCount != newTpeTotalCount)
  293. {
  294. //等上次呼叫的兩百筆執行完才繼續呼叫
  295. if (newTpeNowCount == newTpeOldCount
  296. || newTpeNowCount >= newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
  297. - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
  298. {
  299. //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
  300. //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
  301. //呼叫之前,先記錄目前執行完畢的筆數
  302. //如果正在呼叫中,就不要一直呼叫,不然iis會過載
  303. if (newTpeWCFCalling == false)
  304. {
  305. newTpeOldCount = GetNewTpeFinCountNow();
  306. newTpeWCFCalling = true;
  307. //Task.Run(() => QueryNewTPEByService());
  308. Task.Factory.StartNew(() => QueryNewTPEByService());
  309. }
  310. }
  311. else if (newTpeNowCount < newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
  312. {
  313. //還沒執行完上次呼叫的兩百筆,什麼都不做
  314. }
  315. else
  316. {
  317. //
  318.  
  319. }
  320.  
  321. }
  322. else
  323. {
  324. //已經到達總筆數
  325. StopNewTpeTimer();
  326. //如果臺北市也已經查完了,就紀錄目前無伺服器在大量發送wcf
  327. if (tpeTotalCount == GetTpeFinCountNow())
  328. {
  329. //將目前執行中的主機設定為空字串
  330. UpdateExeSetup("N", "");
  331. }
  332. }
  333.  
  334.  
  335. }
  336.  
  337. //確認每分鐘新北查詢速度
  338. private void queryNewTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e)
  339. {
  340. using (rehouseEntities db = new rehouseEntities())
  341. {
  342. newTpeNowMinuteCount = GetNewTpeFinCountNow();
  343. string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(newTpeNowMinuteCount - newTpeOldMinuteCount);
  344.  
  345. //每三分鐘檢查一次是否速度降為零
  346. //是的話,就重送
  347. if (DateTime.Now.Minute % 3 == 0 && newTpeNowCount != newTpeTotalCount)
  348. {
  349. //如果新北市官網的回應太少導致ResponseRate太低導致該分鐘的速度為0的話,就再度重送
  350. if (newTpeNowMinuteCount - newTpeOldMinuteCount == 0)
  351. {
  352. newTpeOldCount = newTpeNowCount;
  353. }
  354. }
  355.  
  356.  
  357. newTpeOldMinuteCount = GetNewTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
  358. }
  359. }
  360.  
  361.  
  362.  
  363. #endregion
  364.  
  365. #region timer method
  366.  
  367. ///
  368. /// timer週期性的檢查是否可以繼續執行
  369. ///
  370. ///
  371. private bool TimerCheckIfExe()
  372. {
  373. bool result = false;
  374.  
  375. //檢查是否被中斷
  376. string yOrN = "";
  377. string ip = "";
  378. DateTime updateDate;
  379. using (RobotEntities dbRobot = new RobotEntities())
  380. {
  381. //同一時間只能有一個instance執行大量發送
  382. var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault();
  383. yOrN = exeSetup.CODE_VALUE.Trim();
  384. ip = exeSetup.CODE_MEMO.Trim();
  385. updateDate = exeSetup.Update_Date;
  386. }
  387. //依照db裡面的yOrN+ip+updateDate,來判斷是否多個instance重複執行
  388. if (yOrN == "Y" && ip == GetHostIP() && myUpdateDate == updateDate)
  389. {
  390. //可以繼續執行
  391. result = true;
  392. }
  393. else
  394. {
  395. //可能是 Y + 其他ip正在執行
  396. //可能是 N + empty
  397. //以上狀況都要終止執行
  398. //參數設定可能已經由其他instance取代,因此便不再執行UpdateExeSetup();
  399. StopTpeTimer();
  400. StopNewTpeTimer();
  401. result = false;
  402. }
  403.  
  404.  
  405.  
  406. //執行超過八小時一樣強制結束
  407. if (watch.Elapsed.TotalHours > 8)
  408. {
  409. watch.Stop();
  410. StopTpeTimer();
  411. StopNewTpeTimer();
  412. UpdateExeSetup("N", "");
  413. result = false;
  414. }
  415.  
  416. return result;
  417. }
  418.  
  419. //啟動臺北timer
  420. private void TPETimerStart()
  421. {
  422. tpeQueryTPETimer.Start();
  423. tpeAvgSpeedTimer.Start();
  424.  
  425. }
  426.  
  427. //啟動新北timer
  428. private void NewTPETimerStart()
  429. {
  430. newTpeQueryTPETimer.Start();
  431. newTpeAvgSpeedTimer.Start();
  432.  
  433. }
  434.  
  435. private void StopTpeTimer()
  436. {
  437. tpeQueryTPETimer.Stop();
  438. tpeAvgSpeedTimer.Stop();
  439.  
  440.  
  441. }
  442.  
  443. private void StopNewTpeTimer()
  444. {
  445. newTpeQueryTPETimer.Stop();
  446. newTpeAvgSpeedTimer.Stop();
  447.  
  448. }
  449.  
  450. #endregion
  451.  
  452. #region 檢查目前查詢進度method
  453.  
  454. //取得臺北目前查詢完畢的資料筆數
  455. private int GetTpeFinCountNow()
  456. {
  457. using (rehouseEntities db = new rehouseEntities())
  458. {
  459. return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == tpeCityCode).Count();
  460. }
  461. }
  462.  
  463. //取得新北目前查詢完畢的資料筆數
  464. private int GetNewTpeFinCountNow()
  465. {
  466. using (rehouseEntities db = new rehouseEntities())
  467. {
  468. return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == newTpeCityCode).Count();
  469. }
  470. }
  471.  
  472. #endregion
  473.  
  474. #region 呼叫WCF查詢臺北市、新北市
  475.  
  476. //呼叫wcf查詢臺北
  477. private void QueryTPEByService()
  478. {
  479.  
  480. TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
  481. using (rehouseEntities db = new rehouseEntities())
  482. {
  483. var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == tpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
  484. foreach (var p23 in pft23s)
  485. {
  486. sc.GetTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
  487. }
  488.  
  489. }
  490. sc.Close();
  491. tpeWCFCalling = false;//呼叫完畢
  492. }
  493.  
  494. //呼叫wcf查詢臺北
  495. private void QueryNewTPEByService()
  496. {
  497. TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
  498. using (rehouseEntities db = new rehouseEntities())
  499. {
  500. var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == newTpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
  501. foreach (var p23 in pft23s)
  502. {
  503. sc.GetNewTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
  504. }
  505.  
  506. }
  507. sc.Close();
  508. newTpeWCFCalling = false;//呼叫完畢
  509. }
  510.  
  511. #endregion
  512. }
  513. }
參數設定的部分參考winform的完整程式碼即可囉:
http://saltsourcecenter.blogspot.tw/2015/11/webservicewebservice.html

2015年11月23日 星期一

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

Form的外觀:

Form1.cs:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Windows.Forms;
  11. using System.Threading;
  12.  
  13. namespace TPEPublicValuePriceWinForm
  14. {
  15. public partial class Form1 : Form
  16. {
  17. //臺北市的timer
  18. System.Windows.Forms.Timer tpeProgrssBarTimer = new System.Windows.Forms.Timer();
  19. System.Windows.Forms.Timer tpeQueryTPETimer = new System.Windows.Forms.Timer();
  20. System.Windows.Forms.Timer tpeAvgSpeedTimer = new System.Windows.Forms.Timer();
  21.  
  22. //新北市的timer
  23. System.Windows.Forms.Timer newTpeProgrssBarTimer = new System.Windows.Forms.Timer();
  24. System.Windows.Forms.Timer newTpeQueryTPETimer = new System.Windows.Forms.Timer();
  25. System.Windows.Forms.Timer newTpeAvgSpeedTimer = new System.Windows.Forms.Timer();
  26.  
  27. bool tpeWCFCalling = false;
  28. bool newTpeWCFCalling = false;
  29.  
  30.  
  31. //臺北市的狀態記錄
  32. int tpeNowCount;//現在執行完畢的筆數
  33. int tpeOldCount;//五秒前的執行完畢的筆數
  34. int tpeTotalCount;//臺北市總筆數
  35.  
  36. //新北市的狀態記錄
  37. int newTpeNowCount;//現在執行完畢的筆數
  38. int newTpeOldCount;//五秒前的執行完畢的筆數
  39. int newTpeTotalCount;//新北市總筆數
  40.  
  41. //臺北市的平均執行速度狀態記錄
  42. int tpeOldMinuteCount; //一分鐘前執行完畢的筆數
  43. int tpeNowMinuteCount; //目前執行完畢的筆數
  44.  
  45. //新北市的平均執行速度狀態記錄
  46. int newTpeOldMinuteCount; //一分鐘前執行完畢的筆數
  47. int newTpeNowMinuteCount; //目前執行完畢的筆數
  48.  
  49. string tpeCityCode = "0000"; //臺北市城市代碼
  50. string newTpeCityCode = "0001";//新北市程式代碼
  51.  
  52.  
  53.  
  54. public Form1()
  55. {
  56.  
  57. InitializeComponent();
  58. init();
  59.  
  60. }
  61.  
  62. private void init()
  63. {
  64. //初始化筆數
  65. using (rehouseEntities db = new rehouseEntities())
  66. {
  67. //臺北市總筆數
  68. TPETotalCountLbl.Text = db.pft23.Where(p => p.city_code == tpeCityCode).Count().ToString();
  69. tpeTotalCount = Convert.ToInt32(TPETotalCountLbl.Text);
  70. //臺北市執行完畢筆數
  71. TPEFinCountLbl.Text = GetTpeFinCountNow().ToString();
  72.  
  73. //新北市總筆數
  74. NewTPETotalCountLbl.Text = db.pft23.Where(p => p.city_code == newTpeCityCode).Count().ToString();
  75. newTpeTotalCount = Convert.ToInt32(NewTPETotalCountLbl.Text);
  76. //新北市執行完畢筆數
  77. NewTPEFinCountLbl.Text = GetNewTpeFinCountNow().ToString();
  78.  
  79. }
  80.  
  81. //為timer設定事件
  82. //臺北市
  83. tpeProgrssBarTimer.Interval = Convert.ToInt16(Config.ProgressBarCheckTime);//3 secs顯示一次進度
  84. tpeProgrssBarTimer.Tick += new System.EventHandler(tpeProgrssBarTimer_Tick);
  85. tpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
  86. tpeQueryTPETimer.Tick += new System.EventHandler(tpeQueryTPETimer_Tick);
  87. tpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
  88. tpeAvgSpeedTimer.Tick += new System.EventHandler(queryTPEAverageSpeed_Tick);
  89. //新北市
  90. newTpeProgrssBarTimer.Interval = Convert.ToInt16(Config.ProgressBarCheckTime);//3 secs顯示一次進度
  91. newTpeProgrssBarTimer.Tick += new System.EventHandler(newTpeProgrssBarTimer_Tick);
  92. newTpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢
  93. newTpeQueryTPETimer.Tick += new System.EventHandler(newTpeQueryTPETimer_Tick);
  94. newTpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢
  95. newTpeAvgSpeedTimer.Tick += new System.EventHandler(queryNewTPEAverageSpeed_Tick);
  96. }
  97.  
  98. #region control event
  99.  
  100. //按下查詢臺北
  101. private void QueryTPEBtn_Click(object sender, EventArgs e)
  102. {
  103. TPETimerStart();
  104. exeTPEStatusLbl.Text = "執行中";
  105. exeTPEStatusLbl.Text = "執行中";
  106. tpeNowCount = GetTpeFinCountNow();
  107. tpeOldCount = tpeNowCount;
  108. tpeNowMinuteCount = tpeNowCount;
  109. tpeOldMinuteCount = tpeNowCount;
  110. MessageBox.Show("已開始查詢臺北!");
  111. }
  112.  
  113. //停止查詢臺北
  114. private void stopTPEBtn_Click(object sender, EventArgs e)
  115. {
  116. tpeProgrssBarTimer.Stop();
  117. tpeQueryTPETimer.Stop();
  118. tpeAvgSpeedTimer.Stop();
  119. exeTPEStatusLbl.Text = "停止";
  120. MessageBox.Show("已停止查詢臺北!");
  121. }
  122.  
  123. //按下查詢新北
  124. private void QueryNewTPEBtn_Click(object sender, EventArgs e)
  125. {
  126. NewTPETimerStart();
  127. exeNewTPEStatusLbl.Text = "執行中";
  128.  
  129. exeNewTPEStatusLbl.Text = "執行中";
  130. newTpeNowCount = GetNewTpeFinCountNow();
  131. newTpeOldCount = newTpeNowCount;
  132. newTpeNowMinuteCount = newTpeNowCount;
  133. newTpeOldMinuteCount = newTpeNowCount;
  134. MessageBox.Show("已開始查詢新北!");
  135. }
  136.  
  137. //停止查詢新北
  138. private void stopNewTPEBtn_Click(object sender, EventArgs e)
  139. {
  140. newTpeProgrssBarTimer.Stop();
  141. newTpeQueryTPETimer.Stop();
  142. newTpeAvgSpeedTimer.Stop();
  143. exeNewTPEStatusLbl.Text = "停止";
  144. MessageBox.Show("已停止查詢新北!");
  145. }
  146.  
  147.  
  148. #endregion
  149.  
  150. #region Timer Event
  151. //持續更新畫面上查詢臺北的進度
  152. private void tpeProgrssBarTimer_Tick(object sender, EventArgs e)
  153. {
  154.  
  155. TPEFinCountLbl.Text = GetTpeFinCountNow().ToString();
  156. int temp = DateTime.Now.Millisecond % 3;
  157. if(temp ==0)
  158. {
  159. exeTPEStatusLbl.Text = "執行中。。。。。。";
  160. }
  161. else if (temp == 1)
  162. {
  163. exeTPEStatusLbl.Text = "執行中。。。。";
  164. }
  165. else if (temp == 2)
  166. {
  167. exeTPEStatusLbl.Text = "執行中。。";
  168. }
  169. }
  170.  
  171. //每3秒持續呼叫臺北wcf一次
  172. private void tpeQueryTPETimer_Tick(object sender, EventArgs e)
  173. {
  174. tpeNowCount = GetTpeFinCountNow();//現在執行完畢的筆數
  175. //尚未達到總筆數的時候
  176. if (tpeNowCount != tpeTotalCount)
  177. {
  178. //等上次呼叫的兩百筆執行完才繼續呼叫
  179.  
  180. if (tpeNowCount == tpeOldCount
  181. || tpeNowCount >= tpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
  182. - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
  183. {
  184. //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
  185. //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
  186. //呼叫之前,先記錄目前執行完畢的筆數
  187. //如果正在呼叫中,就不要一直呼叫,不然iis會過載
  188. if (tpeWCFCalling == false)
  189. {
  190. tpeOldCount = GetTpeFinCountNow();
  191. tpeWCFCalling = true;
  192. Task.Run(() => QueryTPEByService());
  193. }
  194. }
  195. else if(tpeNowCount < tpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
  196. {
  197. //還沒執行完上次呼叫的兩百筆,什麼都不做
  198. }
  199. else
  200. {
  201. //
  202. }
  203.  
  204. }
  205. else
  206. {
  207. //已經到達總筆數
  208. TPEFinCountLbl.Text = tpeNowCount.ToString();
  209. exeTPEStatusLbl.Text = "已執行完畢!";
  210. StopTpeTimer();
  211. }
  212.  
  213. }
  214.  
  215. //確認每分鐘臺北查詢速度
  216. private void queryTPEAverageSpeed_Tick(object sender, EventArgs e)
  217. {
  218. using (rehouseEntities db = new rehouseEntities())
  219. {
  220. tpeNowMinuteCount = GetTpeFinCountNow();
  221. string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(tpeNowMinuteCount - tpeOldMinuteCount);
  222. TPEAvgSpeedTxt.Text = TPEAvgSpeedTxt.Text + avgSpeedResult + "\r\n";
  223. //每三分鐘檢查一次是否速度降為零
  224. //是的話,就重送
  225. if (DateTime.Now.Minute % 3 == 0 && tpeNowCount != tpeTotalCount)
  226. {
  227. if (tpeNowMinuteCount - tpeOldMinuteCount == 0)
  228. {
  229. tpeOldCount = tpeNowCount;
  230. }
  231. }
  232. tpeOldMinuteCount = GetTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
  233. }
  234. }
  235.  
  236.  
  237. //持續更新畫面上查詢新北的進度
  238. private void newTpeProgrssBarTimer_Tick(object sender, EventArgs e)
  239. {
  240.  
  241. NewTPEFinCountLbl.Text = GetNewTpeFinCountNow().ToString();
  242. int temp = DateTime.Now.Millisecond % 3;
  243. if (temp == 0)
  244. {
  245. exeNewTPEStatusLbl.Text = "執行中。。";
  246. }
  247. else if (temp == 1)
  248. {
  249. exeNewTPEStatusLbl.Text = "執行中。。。。。。";
  250. }
  251. else if (temp == 2)
  252. {
  253. exeNewTPEStatusLbl.Text = "執行中。。。。";
  254. }
  255. }
  256.  
  257. //每五秒持續呼叫新北wcf一次
  258. private void newTpeQueryTPETimer_Tick(object sender, EventArgs e)
  259. {
  260.  
  261. newTpeNowCount = GetNewTpeFinCountNow();//現在執行完畢的筆數
  262. //尚未達到總筆數的時候
  263. if (newTpeNowCount != newTpeTotalCount)
  264. {
  265. //等上次呼叫的兩百筆執行完才繼續呼叫
  266. if (newTpeNowCount == newTpeOldCount
  267. || newTpeNowCount >= newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount)
  268. - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate))
  269. {
  270. //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf
  271. //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆
  272. //呼叫之前,先記錄目前執行完畢的筆數
  273. //如果正在呼叫中,就不要一直呼叫,不然iis會過載
  274. if (newTpeWCFCalling == false)
  275. {
  276. newTpeOldCount = GetNewTpeFinCountNow();
  277. newTpeWCFCalling = true;
  278. Task.Run(() => QueryNewTPEByService());
  279. }
  280. }
  281. else if (newTpeNowCount < newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount))
  282. {
  283. //還沒執行完上次呼叫的兩百筆,什麼都不做
  284. }
  285. else
  286. {
  287. //
  288.  
  289. }
  290.  
  291. }
  292. else
  293. {
  294. //已經到達總筆數
  295. NewTPEFinCountLbl.Text = newTpeNowCount.ToString();
  296. exeNewTPEStatusLbl.Text = "已執行完畢!";
  297. StopNewTpeTimer();
  298. }
  299.  
  300.  
  301. }
  302.  
  303. //確認每分鐘新北查詢速度
  304. private void queryNewTPEAverageSpeed_Tick(object sender, EventArgs e)
  305. {
  306. using (rehouseEntities db = new rehouseEntities())
  307. {
  308. newTpeNowMinuteCount = GetNewTpeFinCountNow();
  309. string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(newTpeNowMinuteCount - newTpeOldMinuteCount);
  310. NewTPEAvgSpeedTxt.Text = NewTPEAvgSpeedTxt.Text + avgSpeedResult + "\r\n";
  311. //每三分鐘檢查一次是否速度降為零
  312. //是的話,就重送
  313. if (DateTime.Now.Minute % 3 == 0 && newTpeNowCount != newTpeTotalCount)
  314. {
  315. //如果新北市官網的回應太少導致ResponseRate太低導致該分鐘的速度為0的話,就再度重送
  316. if (newTpeNowMinuteCount - newTpeOldMinuteCount == 0)
  317. {
  318. newTpeOldCount = newTpeNowCount;
  319. }
  320. }
  321.  
  322. newTpeOldMinuteCount = GetNewTpeFinCountNow();//記錄一分鐘前執行完畢的筆數
  323. }
  324. }
  325.  
  326. private void StopTpeTimer()
  327. {
  328. tpeProgrssBarTimer.Stop();
  329. tpeQueryTPETimer.Stop();
  330. tpeAvgSpeedTimer.Stop();
  331. }
  332.  
  333. private void StopNewTpeTimer()
  334. {
  335. newTpeProgrssBarTimer.Stop();
  336. newTpeQueryTPETimer.Stop();
  337. newTpeAvgSpeedTimer.Stop();
  338. }
  339.  
  340.  
  341. #endregion
  342.  
  343. #region custom method
  344.  
  345. //取得臺北目前查詢完畢的資料筆數
  346. private int GetTpeFinCountNow()
  347. {
  348. using (rehouseEntities db = new rehouseEntities())
  349. {
  350. return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == tpeCityCode).Count();
  351. }
  352. }
  353.  
  354. //呼叫wcf查詢臺北
  355. private void QueryTPEByService()
  356. {
  357.  
  358. TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
  359. using (rehouseEntities db = new rehouseEntities())
  360. {
  361. var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == tpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
  362. foreach (var p23 in pft23s)
  363. {
  364. sc.GetTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
  365. }
  366.  
  367. }
  368. sc.Close();
  369. tpeWCFCalling = false;//呼叫完畢
  370. }
  371.  
  372. //啟動臺北timer
  373. private void TPETimerStart()
  374. {
  375. tpeProgrssBarTimer.Start();
  376. tpeQueryTPETimer.Start();
  377. tpeAvgSpeedTimer.Start();
  378. }
  379.  
  380. //取得新北目前查詢完畢的資料筆數
  381. private int GetNewTpeFinCountNow()
  382. {
  383. using (rehouseEntities db = new rehouseEntities())
  384. {
  385. return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == newTpeCityCode).Count();
  386. }
  387. }
  388.  
  389. //呼叫wcf查詢臺北
  390. private void QueryNewTPEByService()
  391. {
  392. TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient();
  393. using (rehouseEntities db = new rehouseEntities())
  394. {
  395. var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == newTpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount));
  396. foreach (var p23 in pft23s)
  397. {
  398. sc.GetNewTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no);
  399. }
  400.  
  401. }
  402. sc.Close();
  403. newTpeWCFCalling = false;//呼叫完畢
  404. }
  405.  
  406. //啟動新北timer
  407. private void NewTPETimerStart()
  408. {
  409. newTpeProgrssBarTimer.Start();
  410. newTpeQueryTPETimer.Start();
  411. newTpeAvgSpeedTimer.Start();
  412. }
  413. #endregion
  414.  
  415.  
  416. }
  417. }

Config.cs:方便快速存取appsetting用的類別
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Configuration;
  7.  
  8. namespace TPEPublicValuePriceWinForm
  9. {
  10. public class Config
  11. {
  12. public static string SleepTime = GetAppSettings("SleepTime");
  13. public static string ProgressBarCheckTime = GetAppSettings("ProgressBarCheckTime");
  14. public static string AverageSpeedCheckTime = GetAppSettings("AverageSpeedCheckTime");
  15. public static string ResponseLostTime = GetAppSettings("ResponseLostTime");
  16. public static string AutoStopCount = GetAppSettings("AutoStopCount");
  17. public static string AutoInitCount = GetAppSettings("AutoInitCount");
  18. public static string OnceTakeCount = GetAppSettings("OnceTakeCount");
  19. public static string NoResponseRate = GetAppSettings("NoResponseRate");
  20.  
  21. private static string GetAppSettings(string key)
  22. {
  23. return ConfigurationManager.AppSettings[key];
  24. }
  25. }
  26. }
  27.  

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
  1. <%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="ConfigureAwait.aspx.cs" Inherits="ConcurrencyWebForm.ConfigureAwait" %>
  2.  
  3. <!DOCTYPE html>
  4.  
  5. <html xmlns="http://www.w3.org/1999/xhtml">
  6. <head runat="server">
  7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  8. <title></title>
  9. </head>
  10. <body>
  11. <form id="form1" runat="server">
  12. <div>
  13. <asp:Button ID="btnSyncWithoutConfigureAwait" runat="server" Text="SyncWithoutConfigureAwait" OnClick="btnSyncWithoutConfigureAwait_Click" />
  14. <br />
  15. <asp:Button ID="btnSyncWithConfigureAwait" runat="server" Text="SyncWithConfigureAwait" OnClick="btnSyncWithConfigureAwait_Click" />
  16. <br />
  17. <asp:Button ID="btnAsyncWithConfigureAwait" runat="server" Text="AsyncWithConfigureAwait" OnClick="btnAsyncWithConfigureAwait_Click" />
  18. </div>
  19. </form>
  20. </body>
  21. </html>
  22.  
ConfigureAwait.aspx.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using System.Web;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8.  
  9. namespace ConcurrencyWebForm
  10. {
  11. public partial class ConfigureAwait : System.Web.UI.Page
  12. {
  13. protected void Page_Load(object sender, EventArgs e)
  14. {
  15.  
  16. }
  17.  
  18. //此例會造成Deadlock
  19. //ps.以同步的方式執行非同步的function是非常不建議的
  20. protected void btnSyncWithoutConfigureAwait_Click(object sender, EventArgs e)
  21. {
  22. Task tVal = DoSomethingAsync();
  23. string abc = "";
  24. string cde = "";
  25. Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + tVal.Result.ToString() + "');", true);
  26. }
  27. private async Task DoSomethingAsync()
  28. {
  29. int val = 13;
  30. // Asynchronously wait 3 second.
  31. //只是為了讓此library function為非同步執行才用Task.Delay,實際尚無特別意義
  32. await Task.Delay(TimeSpan.FromSeconds(3));
  33. val *= 2;
  34. // Asynchronously wait 3 second.
  35. await Task.Delay(TimeSpan.FromSeconds(3));
  36. return val;
  37. }
  38. protected void btnSyncWithConfigureAwait_Click(object sender, EventArgs e)
  39. {
  40. Task tVal = DoSomethingAsyncWithConfigureAwait();
  41. string abc = "";
  42. string cde = "";
  43. Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + tVal.Result.ToString() + "');", true);
  44. }
  45. //.ConfigureAwait(false)另開了context以儲存library function的執行狀態
  46. private async Task DoSomethingAsyncWithConfigureAwait()
  47. {
  48. int val = 13;
  49. // Asynchronously wait 3 second.
  50. //增加了.ConfigureAwait(false)另開了context
  51. await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
  52. val *= 2;
  53. // Asynchronously wait 3 second.
  54. //增加了.ConfigureAwait(false)另開了context
  55. await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
  56. return val;
  57. }
  58. protected async void btnAsyncWithConfigureAwait_Click(object sender, EventArgs e)
  59. {
  60. int intVal = await DoSomethingAsyncWithConfigureAwait();
  61. string abc = "";
  62. string cde = "";
  63. Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('" + intVal.ToString() + "');", true);
  64. }
  65. }
  66. }