C# .NET多线程之Task的使用
- C# .NET多线程之Task的使用
- 背景
- 需求
- Demo展示
- 测试结果
C# .NET多线程之Task的使用
此文简单介绍下笔者的一点学习心得,希望对有需要的网友一些启发,不喜勿喷。
背景
公司最近公众号推送模板消息的需求频发,此公众号有60万以上用户,每次推送的人群由几千至十万以上不等,主要看目标用户群体划分,本来之前公众号很少量用户时,用for循环发送可以满足,但目前推送一个超过十万目标用户的需求需要耗费4h以上,期间不能推送任何其他模板消息,因此笔者想到了多线程。
需求
通过多线程的方式调用微信接口(微信模板消息接口不支持批量数据调用,只能每个目标用户调用一次),减少推送时间,以达到程序的优化。
Demo展示
// An Console Application.class Program{static object lockObj = new object();// 最多同时开启5个线程,此处可根据电脑配置进行适当调整static int maxTask = 5;static void Main(string[] args){List<Task> taskList = new List<Task>();List<User> users = new List<User>();// 模拟5W用户的场景for (int i = 0; i < 50000; i++){User u = new User();u.openId = i.ToString();users.Add(u);}//var result = users.Select(int.Parse).GroupBy(i => i % 10).Select(g => g.ToList()).ToList();// 将User list转换成每10000个用为一组的list,分别分发给每个线程去发送post请求。List<List<User>> listGroup = new List<List<User>>();int j = 10000;for (int i = 0; i < users.Count; i += 10000){List<User> cList = new List<User>();cList = users.Take(j).Skip(i).ToList();j += 10000;listGroup.Add(cList);}// for循环开始时间var forStartTime = DateTime.Now;for (int k = 0; k < users.Count; k++){Console.WriteLine(\"for输出的id:\" + users[k].openId + \" 当前线程为\" + Thread.CurrentThread.ManagedThreadId.ToString(\"00\") + \"号线程\");}// for循环结束时间var forEndTime = DateTime.Now;var threadStartTime = forEndTime;listGroup.ForEach(userlist =>{var task = new Task(() =>{Run(userlist);});task.Start();//Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());if (taskList.Count > maxTask){Task.WaitAny(taskList.ToArray());taskList = taskList.Where(t => t.Status == TaskStatus.Running).ToList();}taskList.Add(task);});// 等待所有线程都执行完,执行主线程操作。Task.WaitAll(taskList.ToArray());taskList = taskList.Where(t => t.Status == TaskStatus.Running).ToList();var forCostTime = forEndTime - forStartTime;var threadEndtime = DateTime.Now;var threadCostTime = threadEndtime - threadStartTime;Console.WriteLine(\"for cost time: \" + forCostTime);Console.WriteLine(\"thread cost time: \" + threadCostTime);Console.ReadLine();}public static void Run(List<User> users){for (int i = 0; i < users.Count; i++){Console.WriteLine(\"thread输出的id:\" + users[i].openId + \" 当前线程为\" + Thread.CurrentThread.ManagedThreadId.ToString(\"00\") + \"号线程\");}}}public class User{public string openId { get; set; }}
测试结果
从测试结果来看,多线程节省了发送时间 但具体执行post请求会节省多少,还要看数据量,server配置,网络条件,等等相关因素的影响。
线程锁
这里笔者多说一点,代码开头有定义线程锁,但是时间匆忙没来得及加,为了保障线程安全还是要加的。
PS: 中午休息时间暂时写到这把,刚好要到上班时间了,欢迎多提宝贵意见,大家共同探讨。