尽量使用异步编程(ASYNC-AWAIT)
异步编程模型是在C#5.0中引入的,并变得非常流行。ASP.NET Core使用相同的异步编程范例来使应用程序更可靠、更快和更稳定。
您应该在代码中使用端到端异步编程。
让我们举一个例子;我们有一个ASP.NET CoreMVC应用程序,中间有一些数据库的操作。正如我们所知道的,它可能有很多分层结构,这都取决于用户的项目架构,但是让我们举一个简单的例子,其中我们有Controller》Repository 层等等。让我们看看如何在控制器层编写示例代码。
[HttpGet] [Route("GetPosts")] public async Task GetPosts() { try { var posts = await postRepository.GetPosts(); if (posts == null) { return NotFound(); } return Ok(posts); } catch (Exception) { return BadRequest(); } }
接下来的代码然是了我们如何在repository 层实现异步编程。
public async Task
> GetPosts() { if (db != null) { return await (from p in db.Post from c in db.Category where p.CategoryId == c.Id select new PostViewModel { PostId = p.PostId, Title = p.Title, Description = p.Description, CategoryId = p.CategoryId, CategoryName = c.Name, CreatedDate = p.CreatedDate }).ToListAsync(); } return null; }
使用异步编程避免TASK.WAIT或TAST.RESULT
在使用异步编程时,我建议您避免使用Task.Wait和Task.Result并尝试使用WAIT,原因如下:
-
它们阻塞线程直到任务完成,并等待任务完成。等待同步阻塞线程,直到任务完成。
-
Wait 和 Task.Result 在AggregateException中包含所有类型的异常,并在在执行异常处理时增加复杂性。如果您使用的是等待await 而不是 Task.Wait和Task.Result的话,那么您就不必担心异常的处理了。
-
有时,它们都会阻塞当前线程并创建死锁。
-
只有在并行任务执行正在进行时才能使用Wait 和Task.Result 。我们建议您不要在异步编程中使用它。
下面让我们分别演示下正确使用以及不建议使用Task.Wait 的例子,来加深理解吧!
// 正确的例子 Task task = DoWork(); await task; // 不建议使用的例子 Task task = DoWork(); task.Wait();
下面让我们分别演示下正确使用以及不规范使用Task.Result 的例子,来加深理解吧!
// Good Performance on UI Tasktask = GetEmployeeName(); txtEmployeeName.Text = await task; // Bad Performance on UI Task task = GetEmployeeName(); txtEmployeeName.Text = task.Result;
异步执行I/O操作
在执行I/O操作时,您应该异步执行它们,这样就不会影响其他进程。I/O操作意味着对文件执行一些操作,比如上传或检索文件。它可以是任何操作如:图像上传,文件上传或其他任何操作。如果您试图以同步的方式完成它,那么它会阻塞主线程并停止其他后台执行,直到I/O完成为止。因此,从提升性能上来说,您在对I/O进行操作时应该始终进行异步执行。
我们有很多异步方法可用于I/O操作,如ReadAsync、WriteAsync、FlushAysnc等。下面是一个简单的例子,说明我们如何异步创建一个文件的副本。
public async void CreateCopyOfFile() { string dir = @"c:\Mukesh\files\"; using (StreamReader objStreamReader= File.OpenText(dir + "test.txt")) { using (StreamWriter objStreamWriter= File.CreateText(dir+ "copy_test.txt")) { await CopyFileToTarget(objStreamReader, objStreamWriter); } } } public async Task CopyFileToTarget(StreamReader objStreamReader, StreamWriter objStreamWriter) { int num; char[] buffer = new char[0x1000]; while ((num= await objStreamReader.ReadAsync(buffer, 0, buffer.Length)) != 0) { await objStreamWriter.WriteAsync(buffer, 0, num); } }