2015年5月7日 星期四

Async/Await、Task產生執行緒

之前一直認為,Async/Await跟Task一樣都會建出新的執行緒,這是錯誤的,Await是用主執行緒,遇到真正的Async方法(ex:HttpClient.GetAsync)或手動執行的Task.Run或Task.Factory.StartNew,這樣才會建立出新的執行緒

//主執行緒ID
Console.WriteLine(string.Format("Main:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId));

//Task執行緒ID
Task t = Task.Run(() => { Console.WriteLine(string.Format("Task:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); });

//使用Await呼叫方法
await GetAwaitThreadId();

//等候Task完成
t.Wait();

async Task GetAwaitThreadId()
{
  //Await方法執行緒ID
  Console.WriteLine(string.Format("Await:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId));
}



另外,當呼叫非同步方法時,在前半部的程式碼(Await之前),依然是原本的執行緒在執行,遇到Await時,原本的執行緒會回到呼叫端
後半部的程式碼(Await之後),會暫時被保留,等到要等待的工作完成以後,會另外找一條執行緒出來執行後半部程式碼
//呼叫方法
Task t = PrintAwaitThreadId();
for (int i = 0; i < 10; i++)
{
  //列出目前執行緒
  Console.WriteLine(string.Format("Main[{1}]:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId, i));
  //產生新的執行緒做時間延遲
  await Task.Delay(rnd.Next(1, 10));
}
await t;

async Task PrintAwaitThreadId()
{
  for (int i = 0; i < 10; i++)
  {
    //列出目前執行緒
    Console.WriteLine(string.Format("Await[{1}]:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId, i));
    //產生新的執行緒做時間延遲
    await Task.Delay(rnd.Next(1, 10));
  }
}





4 則留言 :

Related Posts Plugin for WordPress, Blogger...