尽量使用异步编程(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<List<PostViewModel>> 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
Task<string> task = GetEmployeeName();
txtEmployeeName.Text = await task;
// Bad Performance on UI
Task<string> 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:Mukeshfiles";
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);
}
}