利用SemaphoreSlim類別來進行async/await非同步工作排程

非同步程式如果不是用在處理大量的事情,似乎就沒有存在的意義了。之前在處理非同步且大量工作的作法,是真的使用System.Threading.Tasks.Task.Factory.StartNew去硬刻出每一個步驟,這樣的缺點是會導致程式碼又臭又長,今日,我們可以使用SemaphoreSlim來幫我降低一下程式碼的複雜性,我大概以後都會靠SemaphoreSlim來幫我進行工作排程的控制了吧!

Console程式碼範例如下:

namespace SemaphoreSlimTest
{
  class Program
  {
    //建立結果集收納處
    private System.Collections.Generic.List<string> oResult = new System.Collections.Generic.List<string>();
    //建立工作排程
    private async System.Threading.Tasks.Task PushToTask(System.Collections.Generic.IList<string> oURLs)
    {
      System.Collections.Generic.List<System.Threading.Tasks.Task> oTasks = new System.Collections.Generic.List<System.Threading.Tasks.Task>();
      System.Threading.SemaphoreSlim oControl = new System.Threading.SemaphoreSlim(oURLs.Count);
      foreach (var cURL in oURLs)
      {
        await oControl.WaitAsync();
        oTasks.Add(System.Threading.Tasks.Task.Run(async () =>
        {
          try
          {
            var oWC = new System.Net.WebClient();
            string cTemp = await oWC.DownloadStringTaskAsync(new System.Uri(cURL));
            oResult.Add(cTemp);
          }
          catch (System.Exception ex)
          {
            System.Console.WriteLine(ex.ToString());
          }
          finally
          {
            oControl.Release();
          }
        }));
      }
      //最終等待
      await System.Threading.Tasks.Task.WhenAll(oTasks);
      //列印出結果
      foreach (var item in oResult)
      {
        System.Console.Write(item);
      }
    }
    
    //主控台
    static void Main(string[] args)
    {
      //利用免費服務,傳回JSON字串
      string[] oURL = {
        "http://headers.jsontest.com/",
        "http://echo.jsontest.com/name/john"
      };
      System.Console.WriteLine(@"/* STEP.A */");
      var a = new Program();
      var oObj = a.PushToTask(oURL);
      System.Console.WriteLine(@"/* STEP.B */");
      //這邊創造一個逼近處理臨界點的等待,讓結果出現隨機跳動
      System.Threading.Thread.Sleep(320);
      System.Console.WriteLine(@"/* STEP.C */");
      System.Console.Read();
    }
  }
}

輸出結果範例:

延遲後比JSON回傳值還快!

JSON回傳值比延遲後還快!

相關參考:

System.Threading.SemaphoreSlim System.Threading.Tasks.Task aSync aWait