我们使用异步编程可以自己开辟线程,也可以使用async,await关键字来实现
例如我们在主线程直接执行一个方法是会阻塞主线程的
static void Main(string[] args) { Console.WriteLine("主线程测试开始.."); Show(); Console.WriteLine("主线程测试结束.."); Console.ReadLine(); } static void Show() { for (int i = 0; i < 5; i++) { Console.WriteLine("异步执行" + i.ToString() + ".."); Task.Delay(1000); //模拟耗时操作 } }
输出完后,主线程才会执行
下面我们使用async,await来实现一个没有返回值的异步方法
没有返回值的异步方法很简单,写好了我们直接调用就好了
static void Main(string[] args) { Console.WriteLine("主线程测试开始.."); ShowAsync(); Console.WriteLine("主线程测试结束.."); Console.ReadLine(); } static async void ShowAsync() { for (int i = 0; i < 5; i++) { Console.WriteLine("异步执行" + i.ToString() + ".."); await Task.Delay(1000); //模拟耗时操作 } }
效果如下,可以看到并没有阻塞主线程:
这里要注意Task.Delay返回的就是一个Task,所以前面可以使用await等待他
下面我们使用async,await来实现一个有返回值的异步方法
由于有返回值不想去影响主函数的方法,我们需要写一个方法来中转一下,在这个中转方法中去取到返回值
当然也可以把调用他的方法也修改为可以等待的异步方法,如果不想修改它就单独写一个方法吧
class Program { static void Main(string[] args) { Console.WriteLine("主线程测试开始.."); MethodAsync(); Console.WriteLine("主线程测试结束.."); Console.ReadLine(); } /// <summary> /// 获取返回值的中转方法 /// </summary> static async void MethodAsync() { Console.WriteLine("开始异步代码"); int result = await ShowRAsync(); Console.WriteLine("异步代码执行完毕" + result); } static async Task<int> ShowRAsync() { for (int i = 0; i < 5; i++) { Console.WriteLine("异步执行" + i.ToString() + ".."); await Task.Delay(1000); //模拟耗时操作 } return 200; } }
效果如下:
tip:这里的ShowRAsync方法是返回的一个task,所以调用它的方法MethodAsync也可以使用await方法等待
相当于加了await就可以得到一个task的执行,但是那个方法必须申明async,那个方法就是一个异步方法
如果在方法当中不需要等待返回值,只是一个异步调用的话,就没有必要去使用async了,直接Task.Run去异步执行就好了
例如提供一个很简单的异步调用日志的方法
public static void AddLogAsync(string content, string type, string remark) { Task.Run(() => { AddLog(content, type, remark); }); }
有返回值:
public Task<int> AddTNMessageAsync(TNMessage _message) { return Task.Run<int>(() => { int count = EfHelper.Add(_message); return count; }); }
查询数据库的时候的异步(ef 异步):
public Task<BlogSet> GetBlogSetByUIdAsync(int? _userid) { return context.BlogSet.Where(a => a.UserId == _userid).FirstOrDefaultAsync(); }
微软官方的 一个例子:
public class PriorityListViewComponent : ViewComponent { private readonly ToDoContext db; public PriorityListViewComponent(ToDoContext context) { db = context; } public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone) { var items = await GetItemsAsync(maxPriority, isDone); return View(items); } private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone) { return db.ToDo.Where(x => x.IsDone == isDone && x.Priority <= maxPriority).ToListAsync(); } }
我的个人理解:
async,await其实里边就是开辟的线程,用这两个可以形成一种标准,一种规范,让人一看就知道是一个异步方法。也封装了很多,让我们方便使用。如果不需要返回值的话,直接调用。如果需要取到返回值就用另外一个包含async的去做一下中转,当然如果想把异步方法当同步使用也可以
另外他们一般都配合task使用
欢迎加群讨论技术,群:677373950(满了,可以加,但通过不了),2群:656732739