[.NET] async and await : 使用實例

C#非同步的async /await 使用實例
主要區分兩種呼叫方式
demo1:模擬同步作業,但不卡住UI Thread,依序完成
demo2: fork asyncJob後,繼續做Job A,Job B,最後await等待完成!

以下兩種方式 都可達到執行LongJob 但不卡住原本UI Thread的效果

demo1:直接接收結果
string result = await WaitAsyncLongJob(5);  

   //demo 1
        //string result= await WaitAsyncLongJob
        //因為內含await,必須加上async: async void btnStart_Click
        private async void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("========================");
            MyLog("開始");
            Console.WriteLine("1.1 threadID:" + Thread.CurrentThread.ManagedThreadId);
            MyLog("執行:string result=WaitAsyncLongJob(5),等待結果,但不卡住UI");
            string result = await WaitAsyncLongJob(5);
            MyLog("結果:" + result);
            MyLog("執行:其他job A (同步Sleep 5秒),卡住UI");
            this.Refresh();
            SyncJob(5);
            this.Refresh();
            MyLog("執行:其他job B (同步Sleep 3秒),卡住UI");
            this.Refresh();
            SyncJob(3);
            MyLog("結束");
            Console.WriteLine("========================");
        }


 


demo2:使用兩段Task<string> result 及 await接收
 Task<string> result = WaitAsyncLongJob(5);
 string done = await result;    

 //demo 2         
        //Task<T> result=waitAsyncLongJob(5)
        //中間繼續做其他事
        //string done=await result
        private async void btnStartDo_Click(object sender, EventArgs e)
        {
            Console.WriteLine("========================");
            MyLog("開始");
            Console.WriteLine("1.1 threadID:" + Thread.CurrentThread.ManagedThreadId);
            MyLog("執行:Task<string> result= WaitAsyncLongJob 5秒");
            Task<string> result = WaitAsyncLongJob(5);            
            MyLog("執行期間UI不會卡住");
            MyLog("執行:string done=await result");
            string done = await result;            
            MyLog("等待結果,result=" + done);
            Console.WriteLine("1.2 threadID:" + Thread.CurrentThread.ManagedThreadId);        
            MyLog("結束");
            Console.WriteLine("========================");
        }


備註:WaitAsyncLongJob 為執行一外部程式
此log job 使用Task.Run 來另起Thread 執行外部程式
可用Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 觀察threadID
 

 //demo1-1
        //內用await task.run(()=>{} 內部執行的程序會另起thread
        public async Task<string> WaitAsyncLongJob(int count)
        {
            Console.WriteLine("2.1 threadID:" + Thread.CurrentThread.ManagedThreadId);
            //await Task.Delay(count * 1000); //非同步作業 task.delay
            await Task.Run(() =>              //Task.Run:另起Thread執行
            {

                Console.WriteLine("2.2 另起threadID:" + Thread.CurrentThread.ManagedThreadId);
                //執行外部程式
                var proc1 = new System.Diagnostics.ProcessStartInfo();
                string anyCommand = "ping localhost  -l 5000 -n " + count.ToString()  ;
                proc1.UseShellExecute = true;
                proc1.WorkingDirectory = @"C:\Windows\System32";
                proc1.FileName = @"C:\Windows\System32\cmd.exe";
                proc1.Verb = "runas";
                proc1.Arguments = "/c " + anyCommand;
                proc1.CreateNoWindow = false;
                proc1.UseShellExecute = false;
                Process cmd = Process.Start(proc1);
                cmd.WaitForExit(); //等待執行完成
            });
            return "WaitAsyncJob finished time:" + DateTime.Now.ToString("HH:mm:ss.fff") ;
        }