国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

為什么要放棄使用Thread.Sleep

2024-07-10 13:29:59
字體:
來源:轉載
供稿:網友

前言

此文并不是說要完全放棄使用Thread.Sleep,而是要說明在符合哪些情況下使用!

場景

很多時候,我們會需要一個定時服務來處理業務。

但并不是死死的每隔N分鐘執行一次那種,而是在一次處理完后,算好下一次處理的時間點。

當到達此時間點,觸發程序重新開始執行代碼。

普遍做法

普遍的情況下,都是使用while(true){Thread.Sleep()}來實現,廢話不多話,看代碼版本1:

class Program{  static void Main(string[] args)  {    var workLists = new List<string>() { "任務1", "任務2", "任務3", "任務4" };    foreach (var task in workLists)    {      var thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Work.DoWork));      thread.Start(task);    }		    }}
class Work{  public static void DoWork(object target)  {    var taskType = target as string;    var interval = 1 * 60 * 1000;//處理失敗,1分鐘后重試    var maxTimes = 5;    var retryTimes = 0;    while (true)    {      while (retryTimes < maxTimes)      {        var ok = Proccess(taskType);        if (ok)        {          retryTimes = maxTimes;        }        else        {          retryTimes++;          System.Threading.Thread.Sleep(interval);        }      }      var tim = GetTotalMillisecondsForNext();//計算離下一次開始處理的時間				      System.Threading.Thread.Sleep(tim);//掛起一段時間后,重新喚醒      retryTimes = 0;    }  }  private static bool Proccess(string taskType)  {    Console.WriteLine("開始執行處理:{0}", taskType);    return true;  }  private static int GetTotalMillisecondsForNext()  {    //這里根據自己的業務來決定    return 2 * 1000;  }}

代碼簡單易懂。

分析

版本1中,循環強制創建線程,并使用System.Threading.Thread.Sleep(tim)來掛起線程,然后重新喚醒。

這種方式不好之處在于:占用系統線程資源,是一種浪費。如同占著茅坑不拉屎!線程是一種十分寶貴的資源,創建,銷毀,切換 都是相當耗性能的。

當Sleep的時候,就等于說:現在我不用,但是你也別想用。你要用?自己去Create一個。

有的人說,Sleep的時候 不占用CPU啊!對,是不占用CPU ,但是占著線程資源,阻礙系統的線程調度!

可以參考下 這文章

Threads are a limited resource, they take approximately 200,000 cycles to create and about 100,000 cycles to destroy. By default they reserve 1 megabyte of virtual memory for its stack and use 2,000-8,000 cycles for each context switch. This makes any waiting thread a   huge  waste.

改進

使用System.Timers.Timer來改進我們的程序。當執行處理業務的代碼時,首先把timer停止,處理完畢后,算好一次執行的時間點,賦給timer并啟動,看代碼版本2

class Program{  static void Main(string[] args)  {    var workLists = new List<string>() { "任務1", "任務2", "任務3", "任務4" };    Parallel.ForEach(workLists,      new ParallelOptions() { MaxDegreeOfParallelism = 3 },      (task) => { new Work2() { TaskType = task }.DoWork(); });    Console.ReadLine();  }}
class Work2  {    private Timer _workTimer;    public string TaskType { get; set; }    public void DoWork()    {      _workTimer = new System.Timers.Timer();      _workTimer.Interval = 1000;      _workTimer.Elapsed += new ElapsedEventHandler(TimerHanlder);      _workTimer.Start();    }    private void TimerHanlder(object sender, ElapsedEventArgs e)    {      _workTimer.Stop();      var interval = 1 * 60 * 1000;//處理失敗,1分鐘后重試      var maxTimes = 5;      var retryTimes = 0;      while (retryTimes < maxTimes)      {        var ok = Proccess();        if (ok)        {          retryTimes = maxTimes;        }        else        {          retryTimes++;          System.Threading.Thread.Sleep(interval);        }      }      var times = GetTotalSecondsForNext();      Console.WriteLine("{0}秒后重新執行", times);      _workTimer.Interval = times * 1000;//計算離下一次開始處理的時間      _workTimer.Start();    }    private bool Proccess()    {      Console.WriteLine("開始執行處理:{0}", TaskType);      return true;    }    private int GetTotalSecondsForNext()    {      //這里根據自己的業務來決定      return 3;    }  }

特別說明一下:Main方法中的Console.ReadLine();很重要,讓主線程處于等待的狀態,子線程就可以一直執行下去不中斷

總結

1:使用Task,而不是使用new System.Threading.Thread。是否要創建線程,應該讓系統來決定,利用可復用資源

2: System.Threading.Thread.Sleep(interval);只合適在 "有限度的 " 循環場景中,比如 最多重試N次、倒計時等等

如果不對之處,請各位斧正!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 叶城县| 正阳县| 安福县| 腾冲县| 东方市| 齐河县| 江西省| 浙江省| 伊金霍洛旗| 浪卡子县| 晋城| 阿瓦提县| 望都县| 翁牛特旗| 潜江市| 双牌县| 湘潭市| 宣汉县| 白城市| 水城县| 山阴县| 平潭县| 涪陵区| 焉耆| 阿拉善左旗| 大庆市| 彭山县| 璧山县| 汝南县| 南陵县| 安龙县| 隆回县| 阿拉善右旗| 长宁区| 麻江县| 五常市| 屏南县| 招远市| 呈贡县| 峨山| 武清区|