<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      實現(xiàn)一個“計劃任務(wù)”機制

      概述

      最近接到一個任務(wù) 要做一個《計劃任務(wù)》的東西。簡而言之的說 就是事先設(shè)定好時間 定期執(zhí)行指定代碼的功能 我們這個很簡單 就是每天或者每幾天 那天的一個固定時間比如23:20執(zhí)行一段固定代碼,好,看一個界面

       

       

      是不是很熟悉 哇哈哈哈,類似 Windows自帶的 計劃任務(wù)功能。 對就是這個。按說的話微軟自家的東西 肯定有對應(yīng)的接口或者 方便銜接的東西,于是網(wǎng)上找來找去 ,最終的結(jié)果還是沒有采用他,一個原因是Windows自帶的計劃任務(wù)功能太復(fù)雜 我根本用不了那么多,第二個原因是沒有找到一個讓我舒心的調(diào)用方式。期間也找過其它的第三方的東西比如quartz 是很牛逼 看了下也是扯淡 大部頭的東西 又是要安裝這安裝那的 不適合我的簡易需求環(huán)境。

      實現(xiàn)原理

      后來靜下心來仔細(xì)想了下 憑什么到指定時間執(zhí)行指定代碼 ,還不是程序開始的時候根據(jù)計劃任務(wù)的時間進行了一個計算 然后設(shè)置一個timer讓代碼到期執(zhí)行嗎,難道還有什么其他歪可以找嗎?搞清楚了事情的本質(zhì)接下來就好辦了,就像期間找過一個mysql不能登錄的問題網(wǎng)上只說啥啥啥方式在命令行輸入 仔細(xì)細(xì)看一下那個圖上的語句明顯是一個mysql的控制臺并不一定要按照他說的流程打開 有可能我沒添加環(huán)境變量各種原因打不開 我直接運行mysql控制臺就好了, 所有做事情做不通前要想一下為很么 會好辦的多。計劃任務(wù)本來不就是算過期時間嗎?什么你懷疑timer不穩(wěn)定?不用timer用什么?按說時間計算是操作系統(tǒng)自暴露的一個API最基本的一個功能,就像文件讀取 就那樣了對于我們搞應(yīng)用開發(fā)的 已經(jīng)沒有更底層的可以挖了。就算你拿C++來 我相信還是只有用類似timer的這種玩意兒 不相信還有其他歪可以找。timer不穩(wěn)定 不要使用winform界面的那個timer 那玩意兒估計確實不穩(wěn)定 命名空間下有好幾個同名的東西。其實過程無法就是程序啟動的時候計算過期時間 按從設(shè)定之處開始算 接下來什么時候執(zhí)行 ,一個timer 加計劃任務(wù)數(shù)據(jù) 經(jīng)過精密的邏輯編程即可解決所有問題 不用去搞任何第三方的東西 ,并且我還有可控的 銜接友好的 界面 進行 任務(wù)管理。

      實現(xiàn)

      其中最主要的是構(gòu)建一個ScheduleItemObj對象,里面有任務(wù)開始時間 間隔天數(shù) 任務(wù)的當(dāng)天執(zhí)行時間 ,相信聰明如你 ,最重要的就是 里面有一個timer 然后 一個委托 委托里面是你要執(zhí)行的代碼,然后就是初始化方法 初始化的時候進行邏輯計算 確定下次執(zhí)行時間 設(shè)置timer ,當(dāng)timer往后每次執(zhí)行的時候自動計算下次時間 然后設(shè)置timer ,如此往復(fù)即可。多個任務(wù)放一個list里 通過propertyChange 進行界面更新,與管理。整個程序的結(jié)構(gòu)大概就是這樣了。我們使用的是System.Timers.Timer

      以下是實現(xiàn)代碼:注意最重要的一段代碼是計算下次任務(wù)執(zhí)行時間邏輯的處理,執(zhí)行時間的機制:從創(chuàng)建的當(dāng)天 的指定時間 ,每過指定單位量時間執(zhí)行計劃任務(wù),比如每天10:10:10 執(zhí)行,如果創(chuàng)建的時候是09:00:00 則當(dāng)天的 10:10:10 首次執(zhí)行 往后以此類推。如果創(chuàng)建的時候是11:00:00 則在下一天的 10:10:10 首次執(zhí)行 往后以此類推。配置一次就可以了 只要程序運行著 計劃任務(wù)就會在指定日期,不論是中途手動退出程序重新開,計算機重啟,都無需干預(yù) ,會自動按照計劃任務(wù)列表里來執(zhí)行,執(zhí)行完后會自動刷新下次執(zhí)行時間 和歷史執(zhí)行記錄。代碼的注釋把以上原理闡述的很清楚。

      void timer_Elapsed(object sender, ElapsedEventArgs e)
              {
                  try
                  {
                      if (Started == false)//首次添加任務(wù) 或者程序剛啟動 安排接下來執(zhí)行時間
                      {
                          //進行首次的當(dāng)天執(zhí)行
                          DateTime now = DateTime.Now;
      
                          DateTime actionTime;
                          DateTimeFormatInfo dtfi = new CultureInfo("zh-CN", false).DateTimeFormat;
                          bool convertok = DateTime.TryParseExact(Time, "HH:mm:ss", dtfi, DateTimeStyles.None, out actionTime);
                          if (convertok == false)
                              return;
      
                          //年月日替換為 創(chuàng)建之日的 //開始時間必須從創(chuàng)建之時 開始算               
      
                          switch (DaysUnit)
                          {
                              case "天"://如果躍遷為天 替換掉 從當(dāng)天的天開始算(時分秒 以計劃設(shè)定為準(zhǔn))
                                  actionTime = new DateTime(CreateAt.Year, CreateAt.Month, CreateAt.Day, actionTime.Hour, actionTime.Minute, actionTime.Second);
                                  break;
      
                              case "時"://如果躍遷為時 替換掉 從當(dāng)天的天.時開始算(分秒 以計劃設(shè)定為準(zhǔn))
                                  actionTime = new DateTime(CreateAt.Year, CreateAt.Month, CreateAt.Day, CreateAt.Hour, actionTime.Minute, actionTime.Second);
                                  break;
      
                              case "分"://如果躍遷為分 替換掉 從當(dāng)天的天.時.分開始算(秒 以計劃設(shè)定為準(zhǔn))
                                  actionTime = new DateTime(CreateAt.Year, CreateAt.Month, CreateAt.Day, CreateAt.Hour, CreateAt.Minute, actionTime.Second);
                                  break;
                              default:
                                  break;
                          }
      
      
                          double interval = (actionTime - now).TotalMilliseconds;
                          if ((actionTime - now).TotalMilliseconds <= 0)//計劃時間在當(dāng)前時間以前
                          {
                              //設(shè)置下次執(zhí)行時間                       
      
                              NextActionAt = actionTime;
      
      
      
                              while (interval <= 0)
                              {
      
                                  //如果很久沒有啟動程序了 加了躍遷 都還是在歷史日期
      
                                  //一直加日期 直到加到超過當(dāng)前日期
                                  switch (DaysUnit)
                                  {
                                      case "天":
                                          actionTime = actionTime.AddDays(Days);
                                          break;
      
                                      case "時":
                                          actionTime = actionTime.AddHours(Days);
                                          break;
      
                                      case "分":
                                          actionTime = actionTime.AddMinutes(Days);
                                          break;
                                      default:
                                          break;
                                  }
      
                                  interval = (actionTime - now).TotalMilliseconds;
                              }
                          }
      
                          //此處必定已經(jīng)累加到interval躍遷大于0了
                          //Console.WriteLine("aaa");
                          if (interval > 0)
                          {
                              NextActionAt = actionTime;
      
                              timer.Interval = interval;
                              timer.AutoReset = false;
                              timer.Start();
      
      
                              Console.WriteLine(ID + "初始化");
      
                              Started = true;
                          }
      
                      }
                      else//運行中
                      {
                          DateTime now = DateTime.Now;
                          Console.WriteLine(ID + "執(zhí)行于:" + NextActionAt.ToString());
      
      
                          try
                          {
      
                              //串口操作
                              ComDevice.Open();
                              byte[] data1 = new byte[] { 0xAA };
                              byte[] data2 = new byte[] { 0xBB };
                              byte[] data3 = new byte[] { 0xCC };
                              
                              ComDevice.Write(data1, 0, 1);
                              Thread.Sleep(Spand1 * 1000);
                              ComDevice.Write(data2, 0, 1);
                              Thread.Sleep(Spand2 * 1000);
                              ComDevice.Write(data3, 0, 1);
                              ComDevice.Close();
      
                              //操作完成 更新數(shù)據(jù)庫記錄 何下次action時間  ,并且設(shè)置自身nextActionAt
      
                              if (historyAdd != null)
                              {
                                  History hist = new History();
                                  hist.Success = 1;
                                  hist.SuccessStr = "成功";
                                  hist.ScheduleID = ID;
                                  hist.ActionAt = NextActionAt.Value;
                                  historyAdd.Invoke(hist);
                              }
                          }
                          catch (Exception ex)
                          {
                              LoggerManager.Instance.WriteLog(ex.Message);
                              if (historyAdd != null)
                              {
                                  History hist = new History();
                                  hist.Success = 0;
                                  hist.SuccessStr = "失敗";
                                  hist.ScheduleID = ID;
                                  hist.ActionAt = NextActionAt.Value;
                                  historyAdd.Invoke(hist);
                              }
                          }
                          finally
                          {
                              //無論如何都進行下次的計劃任務(wù)定制
                              //執(zhí)行到此處的時候肯定是actionAt時間到了,只需再加上days即可
                              switch (DaysUnit)
                              {
                                  case "天":
                                      NextActionAt = NextActionAt.Value.AddDays(Days);
                                      break;
      
                                  case "時":
                                      NextActionAt = NextActionAt.Value.AddHours(Days);
                                      break;
      
                                  case "分":
                                      NextActionAt = NextActionAt.Value.AddMinutes(Days);
                                      break;
                                  default:
                                      break;
                              }
      
      
                              timer.Interval = (NextActionAt.Value - now).TotalMilliseconds;
                              timer.AutoReset = false;
                              timer.Start();
                          }
      
      
                      }
                  }
                  catch (Exception ex)
                  {
      
                      Console.WriteLine("遇到錯誤:" + ex.Message);
                      LoggerManager.Instance.WriteLog(ex.Message);
                  }
      
              }

      在程序啟動的時候從access數(shù)據(jù)庫讀取記錄 然后把所有計劃任務(wù)都計算并啟動一遍。

      public void StartSchedule()
      {
          //清理以前的
          if (RunningSchedule != null)
          {
              for (int i = 0; i < RunningSchedule.Count; i++)
              {
                  RunningSchedule[i].TimerClose();
              }
              RunningSchedule.Clear();
          }
          else
          {
              RunningSchedule = new ObservableCollection<ScheduleItemObj>();
          }
      
      
          if (Data == null || Data.Count == 0)
          {
              return;
          }
      
          for (int i = 0; i < Data.Count; i++)
          {
              RunningSchedule.Add(Data[i]);
              Data[i].historyAdd += new Action<History>((hist) => {
      
                  uiDispatcher.Invoke(new Action(() => { 
                  
                  this.AddDBHistory(hist);
                  this.AddHistoryVirtual(hist);
                  }));
              });
              Data[i].Start();
          }
      }
      

       

      當(dāng)然 如果是添加新任務(wù) 我們也是很簡易粗暴的 添加數(shù)據(jù) 然后把所有任務(wù)停止,停止的時候會回收資源, 然后再啟動一遍 ,這樣便于我們更簡易的控制。

      if (sw.ShowDialog() == true)
      {
          vm.AddSchedule(sw.day, sw.time.ToString("HH:mm:ss"),sw.daysUnit);
          vm.StartSchedule();
      }

      然后我們做了一個啟動時自動縮小到任務(wù)欄托盤運行的方式。我們是根據(jù)開始基礎(chǔ)日期 的設(shè)定進行 躍遷 單位 計算下次執(zhí)行時間的 而不是累加,所以程序運行多久都不會出現(xiàn)執(zhí)行時間上的偏差。

      當(dāng)然 有幾個東西要知曉 ,1應(yīng)用程序必須要一直在運行期間計劃任務(wù)才能夠得到成功執(zhí)行,系統(tǒng)沒有登錄的情況下不會得到執(zhí)行。我的運用環(huán)境是滿足的。 要規(guī)避這個問題網(wǎng)上說可以弄成服務(wù)形式的。

      好了完工,上一個運行圖,好,完美,此程序現(xiàn)在已穩(wěn)定運行相當(dāng)長一段時間了,未出過問題。

       

       

       

       

       

       

      posted @ 2020-10-11 23:20  assassinx  閱讀(1026)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产系列丝袜熟女精品视频| 成人无码区在线观看| 在线视频中文字幕二区| 国产日韩AV免费无码一区二区三区| 国产av中文字幕精品| 日韩伦理片| 午夜国产精品福利一二| 国产精品人妻系列21p| 福利一区二区不卡国产| 亚洲精品区二区三区蜜桃| 人妻丝袜中文无码AV影音先锋专区| 精品久久久久国产免费| 天堂а√在线地址中文在线| 亚洲精品在线二区三区| 沈阳市| 无码日韩精品一区二区免费| 亚洲中文字幕有综合久久| 久操资源站| 精品不卡一区二区三区| 国产一区二区三区不卡视频| 欧美成本人视频免费播放| 蜜桃精品成人影片| 无码av永久免费专区麻豆| 色综合一本到久久亚洲91| 欧美亚洲另类自拍偷在线拍| 国产欧美在线手机视频| 国产精品高清一区二区三区| 97se亚洲综合自在线| 国产亚洲精品自在久久vr| 久久天天躁夜夜躁狠狠综合| 久久无码高潮喷水| 国产一区二区三区免费观看| 黄色亚洲一区二区三区四区| 国产成人一区二区三区在线| 亚洲第一区二区快射影院| 精品无人区一码二码三码| 国产SM重味一区二区三区| 亚洲国产在一区二区三区| 秋霞人妻无码中文字幕| japanese无码中文字幕| 亚洲一区二区三区在线观看精品中文 |