我有一个.NET应用程序,在批量导入中处理大约300,000条记录,每条记录需要几秒钟,所以我想并行化这个.在下面的代码中,ProcessWithAnsycDelegates()
和之间有什么区别ProcessWithThreadPool()
?
public class ResultNotification { public EventHandler event Success; public EventHandler event Fail; internal void Notify(bool sucess) {if (success) Success(); else Fail();} } public static class Processor { public ResultNotification ProcessWithAnsycDelegates(Record record) { var r = new ResultNotification(); FuncprocessRecord=new RecordProcessor().ProcessRecord; processRecord.BeginInvoke ( record ,ar => result.Notify(processRecord.EndInvoke(ar)) ,null); return r; } public ResultNotification ProcessWithThreadPool(Record r) { var r = new ResultNotification(); var rp = new RecordProcessor(); ThreadPool.QueueWorkUserItem(_=>result.Notify(rp.ProcessRecord(r))); return r; } }
Thomas Bratt.. 7
这个问题的字面答案是两者都使用线程池,因此如果性能是唯一的考虑因素,差异并不大.
如果问题实际上是关于获得最佳性能,那么知道使用线程池确实存在问题可能会有所帮助.这些包括:
锁定工作队列上的争用
过多的上下文切换.如果你有2个CPU和一系列工作项,那么25个线程并没有真正帮助.最好有2个线程,每个CPU一个
可能值得调查TPL和PLINQ:
并行LINQ在多核处理器上运行查询
并行性能优化多核机器的管理代码
在Visual Studio的下一版本中改进了对并行性的支持
他们给出的TPL使用的一个例子是:
for (int i = 0; i < 100; i++) { a[i] = a[i]*a[i]; }
至:
Parallel.For(0, 100, delegate(int i) { a[i] = a[i]*a[i]; });
chadmyers.. 6
在这种情况下,并不是很多,因为他们都使用引擎盖下的线程池.我会说QueueUserWorkItem()更容易阅读,看看与BeginInvoke有什么关系.
此链接可能有所帮助.这是较旧的信息,但仍然大多适用 http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml
这个问题的字面答案是两者都使用线程池,因此如果性能是唯一的考虑因素,差异并不大.
如果问题实际上是关于获得最佳性能,那么知道使用线程池确实存在问题可能会有所帮助.这些包括:
锁定工作队列上的争用
过多的上下文切换.如果你有2个CPU和一系列工作项,那么25个线程并没有真正帮助.最好有2个线程,每个CPU一个
可能值得调查TPL和PLINQ:
并行LINQ在多核处理器上运行查询
并行性能优化多核机器的管理代码
在Visual Studio的下一版本中改进了对并行性的支持
他们给出的TPL使用的一个例子是:
for (int i = 0; i < 100; i++) { a[i] = a[i]*a[i]; }
至:
Parallel.For(0, 100, delegate(int i) { a[i] = a[i]*a[i]; });
在这种情况下,并不是很多,因为他们都使用引擎盖下的线程池.我会说QueueUserWorkItem()更容易阅读,看看与BeginInvoke有什么关系.
此链接可能有所帮助.这是较旧的信息,但仍然大多适用 http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml