故如虹,知恩;故如月,知明
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
欢迎加群交流技术

c#异步编程task,async,await的一点理解

9409人阅读 2019/6/11 18:01 总访问:3837487 评论:3 收藏:0 手机
分类: .NET


我们使用异步编程可以自己开辟线程,也可以使用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

评价