2019年5月23日 星期四

c# async 和 await 簡易說明

函式前面增加 async 就會成為異步函式(執行過程中不會等待函式執行完畢才往下跑)



/// <summary>
/// 異步函式
/// </summary>
static async void AsyncFun()
{
 // 裡面要有 await 關鍵字

 // await 後面要接回傳 Task 的函式
 // 因為回傳 Task 簡稱他為異步任務

 List<formatter> f_ = new List<formatter>{
  new Formatter("「異步任務」", Color.Red)};

 Print("執行 {0} 『開始』", Color.Yellow, f_.ToArray());
 bool ret_ = await DelayFun();
 Print("執行 {0} 『結束』", Color.Yellow, f_.ToArray());
}


異步函式內需要有await 關鍵字
await 後面要接回傳 Task 的函式
因為回傳 Task 簡稱他為異步任務



/// <summary>
/// 異步任務
/// </summary>
/// <returns>true</returns>
static Task<bool> DelayFun()
{
 return Task.Run(() =>
 {
  List<Formatter> f_ = new List<Formatter>{
   new Formatter("等待五秒", Color.YellowGreen)};

  Print("{0} 開始", Color.Red, f_.ToArray());
  Thread.Sleep(5000);
  Print("{0} 結束", Color.Red, f_.ToArray());
  return true;
 });
}



異步函式呼叫與一般函式一樣
只差在執行中不等待函式執行完


static void Main(string[] args)
{
 ....
 // 異步函式
 List<Formatter> f0_ = new List<Formatter>{
  new Formatter("「異步函式」", Color.Red)};
 Print("執行 {0} 開始", Color.Green, f0_.ToArray());
 AsyncFun();
 Print("執行 {0} 結束", Color.Green, f0_.ToArray());
 ....
}



最後可以看到「異步任務」
在程式執行完畢後
才把任務跑完











利用 .NET Standard 函式庫 的 C# 取得 Git 版本號



這邊遇到找不到 Git 的環境變數
所以在 @"Git\cmd" 做了一些修改
這邊得看看你 Git 的執行檔在那個目錄內
再做調整與修改



public class CommitID
{
 private static string EnvironmentVariable
 {
  get
  {
   string sPath = Environment.GetEnvironmentVariable("Path");
   var result = sPath.Split(';');
   for (int i = 0; i < result.Length; i++)
   {
    if (result[i].Contains(@"Git\cmd"))
    {
     sPath = result[i];
    }

   }
   return sPath;
  }
 }

 public static void GetCommitID()
 {
  string gitPath = System.IO.Path.Combine(EnvironmentVariable, "git.exe");
  Console.WriteLine($"環境路徑:{gitPath}");
  Process p = new Process();
  p.StartInfo.FileName = gitPath;
  p.StartInfo.Arguments = "rev-parse HEAD";
  p.StartInfo.CreateNoWindow = true;
  p.StartInfo.UseShellExecute = false;
  p.StartInfo.RedirectStandardOutput = true;
  p.OutputDataReceived += OnOutputDataReceived;
  p.Start();
  p.BeginOutputReadLine();
  p.WaitForExit();
 }

 private static void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
 {
  if (e != null && !string.IsNullOrEmpty(e.Data))
  {
   ID = e.Data;

   Console.WriteLine(e.Data);
  }
 }

 public static string ID { get; set; } = "";
}


使用方法:
先呼叫 GetCommitID()
之後 ID 就會有 Git 的版本號
他會取得目前執行目錄上的 Git 版本號


























Visual Studio 2017利用 T4 自動產生版本號(寫入 Git 版本號)


「工具」 「擴充功能與更新」

安裝「T4Executer 」後 T4 的關鍵字都會有對應的顏色標示

























安裝 「Devart T4 Editor」可以設定編譯前先執行 T4 範本

























設定編譯前執行 T4 (圖為執行狀態)














設定畫面
























新建文字檔 附檔名為 *.tt
就會出現「轉換所有 T4 範本」
點擊就會執行 T4 範本




















首先註解 AssemblyInfo.cs 裡面的
[assembly: AssemblyFileVersion("0.0.0.0")]

[assembly: AssemblyTitle("ConsoleApp")]
下面的 SharedInfo.tt 檔案(T4 範例)
會自動產生一個 SharedInfo.cs
並自動填入
[assembly: AssemblyFileVersion("0.0.0.0")]

[assembly: AssemblyTitle("ConsoleApp")]
的內容


<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ import namespace="System.IO" #>
<#@ assembly name="$(SolutionDir)\CommitID\bin\Debug\netstandard2.0\MyLibrary.Git.dll" #>
<#@ import namespace="MyLibrary.Git" #>
<#@ assembly name="C:\Program Files\dotnet\sdk\2.1.700-preview-009597\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\netstandard.dll" #>
<#@ output extension=".cs" #>
<#
     int major = 0; 
     int minor = 0; 
     int build = 0; 
     int revision = 0; 
  
     try
     {
         using(var f = File.OpenText(Host.ResolvePath("SharedInfo.cs")))
         {
             // 取值做 +1 使用
             //string maj = f.ReadLine().Replace("//","");
             //string min = f.ReadLine().Replace("//","");
             //string b   = f.ReadLine().Replace("//","");
             //string r   = f.ReadLine().Replace("//","");
  
             // 轉成日期
             string maj = DateTime.Now.Year.ToString();
             string min = DateTime.Now.Month.ToString();
             string b   = DateTime.Now.Day.ToString();
             string r   = DateTime.Now.Minute.ToString() + "0" + DateTime.Now.Second.ToString();

             major    = int.Parse(maj); 
             minor    = int.Parse(min); 
             build    = int.Parse(b); 
             revision = int.Parse(r) + 1; 
         }
     }
     catch
     {
         major    = 1; 
         minor    = 0; 
         build    = 0; 
         revision = 255; 
     }

    // 呼叫自己個函式庫
 CommitID.GetCommitID();
 string gitver = CommitID.ID;
 #>
 //<#= major #>
 //<#= minor #>
 //<#= build #>
 //<#= revision #>

 //<#= gitver #>

 // 
 // This code was generated by a tool. Any changes made manually will be lost
 // the next time this code is regenerated.
 // 
  
 using System.Reflection;
  
 [assembly: AssemblyFileVersion("<#= major #>.<#= minor #>.<#= build #>.<#= revision #>")]
 [assembly: AssemblyTitle("<#= gitver #>")]



MyLibrary.Git 是我寫的 .NET Standard Library
透過


<#@ assembly name="$(SolutionDir)\CommitID\bin\Debug\netstandard2.0\MyLibrary.Git.dll" #>
<#@ import namespace="MyLibrary.Git" #>


使用 .NET Standard Library 還要加入 .NET Standard 的 dll


<#@ assembly name="C:\Program Files\dotnet\sdk\2.1.700-preview-009597\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\netstandard.dll" #>


不然編譯會有錯誤訊息:
錯誤 正在編譯轉換: 類型 'Object' 定義在未參考的組件中。您必須加入組件 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' 的參考。

請依據自己的 dotnet 版本選擇目錄,例如:我的是 net461














Visual Studio 2017/2019 推薦的擴充功能與更新

參考文章: 覺得 Google 的 Blogger 不太順手?透過 HTML 的 iframe 移花接木 HackMD