c# – 多线程为什么简单的多任务不起作用?
var finalList = new List<string>(); var list = new List<int> {1,2,3,4,5,6,7,8,9,10 ................. 999999}; var init = 0; var limitPerThread = 5; var countDownEvent = new CountdownEvent(list.Count); for (var i = 0; i < list.Count; i++) { var listToFilter = list.Skip(init).Take(limitPerThread).ToList(); new Thread(delegate() { Foo(listToFilter); countDownEvent.Signal(); }).Start(); init += limitPerThread; } //wait all to finish countDownEvent.Wait(); private static void Foo(List<int> listToFilter) { var listDone = Boo(listToFilter); lock (Object) { finalList.AddRange(listDone); } } 这不是: var taskList = new List<Task>(); for (var i = 0; i < list.Count; i++) { var listToFilter = list.Skip(init).Take(limitPerThread).ToList(); var task = Task.Factory.StartNew(() => Foo(listToFilter)); taskList.add(task); init += limitPerThread; } //wait all to finish Task.WaitAll(taskList.ToArray()); 此过程最终必须至少创建700个线程.当我使用Thread运行时,它可以工作并创建所有这些.但是使用Task它不会..它似乎没有启动倍数任务异步. 我真的想知道为什么……任何想法? 编辑 PLINQ的另一个版本(如建议的那样). var taskList = new List<Task>(list.Count); Parallel.ForEach(taskList,t => { var listToFilter = list.Skip(init).Take(limitPerThread).ToList(); Foo(listToFilter); init += limitPerThread; t.Start(); }); Task.WaitAll(taskList.ToArray()); EDIT2: public static List<Communication> Foo(List<Dispositive> listToPing) { var listResult = new List<Communication>(); foreach (var item in listToPing) { var listIps = item.listIps; var communication = new Communication { IdDispositive = item.Id }; try { for (var i = 0; i < listIps.Count(); i++) { var oPing = new Ping().Send(listIps.ElementAt(i).IpAddress,10000); if (oPing != null) { if (oPing.Status.Equals(IPStatus.TimedOut) && listIps.Count() > i+1) continue; if (oPing.Status.Equals(IPStatus.TimedOut)) { communication.Result = "NOK"; break; } communication.Result = oPing.Status.Equals(IPStatus.Success) ? "OK" : "NOK"; break; } if (listIps.Count() > i+1) continue; communication.Result = "NOK"; break; } } catch { communication.Result = "NOK"; } finally { listResult.Add(communication); } } return listResult; } 解决方法
任务不是多线程的.它们可以用于它,但大多数它们实际上用于相反的 – 在一个线程上多路复用.
要使用多线程任务,我建议使用Parallel LINQ.它已经有许多优化,例如列表的智能分区,只产生与CPU核心一样多的线程等. 要理解Task和async,请以这种方式考虑它 – 典型的工作负载通常包括需要等待的IO.也许您阅读文件,查询Web服务,或访问数据库等等.关键是 – 你的线程会等待一段时间(至少在CPU周期内),直到你从一些遥远的目的地得到一个响应. 在Olden Days?中,这意味着您的线程被锁定(暂停),直到响应出现.如果你想在此期间做其他事情,你需要生成一个新线程.这是可行的,但效率不高.每个OS线程都带有很大的开销(内存,内核资源).并且你可能最终会有几个线程主动烧毁CPU,这意味着操作系统需要在它们之间切换,这样每个都会获得一点CPU时间,而这些“上下文切换”非常昂贵. 异步更改了该工作流程.现在,您可以在同一个线程上执行多个工作负载.虽然有一项工作正在等待远方来源的结果,但另一项工作可以介入并使用该线程来做其他有用的事情.当第二个工作负载自行等待时,第一个工作负载可以唤醒并继续. 毕竟,产生比CPU内核更多的线程是没有意义的.你不会以这种方式完成更多的工作.恰恰相反 – 更多时间将用于切换线程,并且可用于有用工作的时间更少. 这就是Task / async / await最初设计的目的.然而,并行LINQ也利用它并将其重用于多线程.在这种情况下,您可以这样看待 – 其他线程是您的主线程是您的主线程正在等待的“遥远的目的地”. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |