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") ;
}