普通的async await方法其實是一個同步的異步調用,此方式並不開啟新的線程,只是一個多任務處理模式,只是主線程在運行時不會阻塞卡死。此方式只能調用異步方法。
(使用async和await定義異步方法不會創建新線程,所以使用Thread.Sleep(3000)主線程也會阻塞卡死)
(由於不是開始新線程,所以在方法內頁面的所有控件都可以直接訪問)
而async await Task.Run是一個真實的異步模式,此方式實質就是開啟一個新的托管的線程。並且此方式可以調用同步方法。
(使用await Task.Run定義異步方法會創建新線程,所以使用Thread.Sleep(3000)不影響主線程)
(不考慮資源消耗的情況下,使用await Task.Run貌似是個更好的選擇)(當然開啟新線程會消耗更多的資源)
(由於是開啟新新線程,所以在await Task.Run方法體中就不可以直接調用頁面內控件了,需要使用this.Dispatcher.BeginInvoke調用控件)
task.run 看來就是以前的開一個線程,類似於thread.start
不是必要與await一起使用的
可以單獨使用
加await就是相當於異步同步操作
task才是核心
await和async都是怎么調用的定義
關於線程中更新控件值原則: 如果線程里執行的程序如果一直要更新控件值,那么線程中需要調用控件並且修改值(比如進度條),如果控件只需要線程運行完成后的結果值,那么不應該在線程中調用控件,只需要在線程結束后獲取的值在線程外主線程直接更新控件值就可以了(當然也不是絕對,比如更新的數據量大,那么還是可能造成主線程阻塞,此時在線程內部更新控件值也是個好選擇)
lamada表達式 這種 省了一個委托和傳參
public partial class YiBuTest : Window { public YiBuTest() { InitializeComponent(); } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { } private async void btnClick_Click(object sender, EventArgs e) { // 這里可以做一些不依賴回復的操作 richTextBox1.Text += "\r\n等待服務器回復中.................\n"; //long length = await AccessWebAsync(); long length = await GetAwaitRunString("參數"); richTextBox1.Text += String.Format("\n 回復成功,字節長度為: {0}.\r\n", length); txbMainThreadID.Text = Thread.CurrentThread.ManagedThreadId.ToString(); } #region await調用異步方法(使用async和await定義異步方法不會創建新線程,所以使用Thread.Sleep(3000)主線程也會阻塞卡死)(由於不是開始新線程,所以在方法內頁面的所有控件都可以直接訪問) // 使用C# 5.0中提供的async 和await關鍵字來定義異步方法 // 從代碼中可以看出C#5.0 中定義異步方法就像定義同步方法一樣簡單。 // 使用async和await定義異步方法不會創建新線程, // 它運行在現有線程上執行多個任務. // 此時不知道大家有沒有一個疑問的?在現有線程上(即UI線程上)運行一個耗時的操作時, // 為什么不會堵塞UI線程的呢? // 這個問題的答案就是 當編譯器看到await關鍵字時,線程會 private async Task<long> AccessWebAsync() { MemoryStream content = new MemoryStream(); // 對MSDN發起一個Web請求 HttpWebRequest webRequest = WebRequest.Create("https://docs.microsoft.com/zh-cn/") as HttpWebRequest; if (webRequest != null) { // 返回回復結果 using (WebResponse response = await webRequest.GetResponseAsync()) { using (Stream responseStream = response.GetResponseStream()) { await responseStream.CopyToAsync(content); } } } txbAsynMethodID.Text = Thread.CurrentThread.ManagedThreadId.ToString(); return content.Length; } #endregion #region await調用同步方法await Task.Run(使用await Task.Run定義異步方法會創建新線程,所以使用Thread.Sleep(3000)不影響主線程)(不考慮資源消耗的情況下,使用await Task.Run貌似是個更好的選擇)(當然開啟新線程會消耗更多的資源) //(由於是開啟新新線程,所以在await Task.Run方法體中就不可以直接調用頁面內控件了) private async Task<long> GetAwaitRunString(string str) { var task = await Task.Run<long>(() => { return tongbufangfa(str); }); return task; } private long tongbufangfa(string str) { //線程停頓3秒 Thread.Sleep(3000); MemoryStream content = new MemoryStream(); // 對MSDN發起一個Web請求 HttpWebRequest webRequest = WebRequest.Create("https://docs.microsoft.com/zh-cn/") as HttpWebRequest; if (webRequest != null) { // 返回回復結果 using (WebResponse response = webRequest.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { responseStream.CopyTo(content); } } } return content.Length; } #endregion }