文章出處
文章列表
async/task/await三組合是.NET Framework 4.5帶給.NET開發者的大禮,合理地使用它,可以提高應用程序的吞吐能力。
但是它的使用有點繞人,如果不正確使用,會帶來意想不到的問題——比如await之后一直在等待,等到花兒也謝了,也等不來。
這篇博文將向你展示我們在實際開發中遇到的這個問題。
先看一段ASP.NET MVC示例代碼:
public class BlogController : Controller { public async Task<ActionResult> AwaitDemo() { var responseHtml = GetResponseHtml("http://www.cnblogs.com/"); return Content(responseHtml); } private string GetResponseHtml(string url) { return GetResponseContentAsync(url).Result; } private async Task<string> GetResponseContentAsync(string url) { var httpClient = new System.Net.Http.HttpClient(); var response = await httpClient.GetAsync(url); if (response.StatusCode == System.Net.HttpStatusCode.OK) { return await response.Content.ReadAsStringAsync(); } else { return "error"; } } }
代碼說明:
- 在上面的代碼中,雖然在Action方法之前加了async Task<ActionResult>,但由于在方法體中沒有使用await,所以實際還是以同步的方式執行的,與直接使用ActionResult是一樣的。
- GetResponseHtml是同步方法,GetResponseContentAsync是異步方法,在GetResponseHtml中調用了異步的GetResponseContentAsync。(如果調用的是第三方程序集,我們就不知道在GetResponseHtml中進行了異步調用,所以這個方法的設計是有問題的)
這段代碼執行結果會是怎樣呢?
——結果就是沒有結果,一直在執行。。。
(注:如果在控制臺應用程序中調用同樣的GetResponseHtml,不會出現這個問題)
那如果解決這個問題呢:
解決方法一:在MVC Action中開啟一個Task進行await
public async Task<ActionResult> AwaitDemo() { var responseHtml = await Task.Factory.StartNew(() => GetResponseHtml("http://www.cnblogs.com/")); return Content(responseHtml); }
解決方法二:將GetResponseHtml變成異步方法
public async Task<ActionResult> AwaitDemo() { var responseHtml = await GetResponseHtml("http://www.cnblogs.com/"); return Content(responseHtml); } private async Task<string> GetResponseHtml(string url) { return await GetResponseContentAsync(url); }
顯然,第2個解決方法是更好的。
所以,我們在設計一個方法(method)時,如果調用了async方法,一定要將這個方法本身設計為async的。不然,別人調用時很容易踩著這個坑,然后就一直等啊等。。。等到花兒謝了,電腦冒煙了,也等不到。
【相關鏈接】
文章列表
全站熱搜