ThreadPool QueueUserWorkItem with a list

I would like to use QueueUserWorkItem from ThreadPool. When I use the following code, everything works well.

private int ThreadCountSemaphore = 0; private void (...) { var reportingDataList = new List<LBReportingData>(); ThreadCountSemaphore = reportingDataList.Count; using (var autoResetEvent = new AutoResetEvent(false)) { ThreadPool.QueueUserWorkItem((o) => this.FillReportingData(settings, reportingDataList[0], autoResetEvent)); ThreadPool.QueueUserWorkItem((o) => this.FillReportingData(settings, reportingDataList[1], autoResetEvent)); ThreadPool.QueueUserWorkItem((o) => this.FillReportingData(settings, reportingDataList[2], autoResetEvent)); } } private void FillReportingData(...) { if (Interlocked.Decrement(ref this.ThreadCountSemaphore) == 0) { waitHandle.Set(); } } 

But when I use a list instead of a single method, my program crashes without exception.

 private void (...) { var reportingDataList = new List<LBReportingData>(); ThreadCountSemaphore = reportingDataList.Count; using (var autoResetEvent = new AutoResetEvent(false)) { ThreadPool.QueueUserWorkItem((o) => this.FillReportingData(settings, reportingDataList[i], autoResetEvent)); } } 

What am I wrong? What should I change?

Update

Sorry, I made a mistake in the code. I am using .NET 2.0 with VS2010. Here is the full code:

 private int ThreadCountSemaphore = 0; private IList<LBReportingData> LoadReportsForBatch() { var reportingDataList = new List<LBReportingData>(); var settings = OnNeedEntitySettings(); if (settings.Settings.ReportDefinition != null) { var definitionList = new List<ReportDefinitionen> { ReportDefinitionen.OrgStatus, ReportDefinitionen.Mittelwerte, ReportDefinitionen.Verteilungsstatistik }; using (var autoResetEvent = new AutoResetEvent(false)) { foreach (var reportDefinition in definitionList) { foreach (DataRow row in settings.Settings.ReportDefinition.Select("AuswertungsTyp = " + (int)reportDefinition)) { reportingDataList.Add(new LBReportingData { SourceData = row, ReportType = reportDefinition }); } } ThreadCountSemaphore = reportingDataList.Count; foreach(var reportingDataItem in reportingDataList) { ThreadPool.QueueUserWorkItem((o) => this.FillReportingData(settings, reportingDataItem, autoResetEvent)); } autoResetEvent.WaitOne(); } } return reportingDataList; } private void FillReportingData(IEntitySettings<DSLBUReportDefinition> settings, LBReportingData reportingData, AutoResetEvent waitHandle){ DoSomeWork(); if (Interlocked.Decrement(ref this.ThreadCountSemaphore) == 0) { waitHandle.Set(); } } 

thank

+1
multithreading c # threadpool
Sep 15 '10 at 17:23
source share
2 answers

You delete WaitHandle immediately after work item queues. There is a race between calling Dispose in the main thread and Set in the workflow. There may be other problems, but it's hard to guess because the code is incomplete.

Here's how the template should work.

 using (var finished = new CountdownEvent(1)) { foreach (var item in reportingDataList) { var captured = item; finished.AddCount(); ThreadPool.QueueUserWorkItem( (state) => { try { DoSomeWork(captured); // FillReportingData? } finally { finished.Signal(); } }, null); } finished.Signal(); finished.Wait(); } 

The code uses the CountdownEvent class. It is available in .NET 4.0 or as part of the Reactive Extensions download.

+2
Sep 15 '10 at 17:49
source share

As Hans pointed out, it’s not clear where I come from. But also I see how your deletion block exited and deleted because you are not using WaitOne on it (or you did not copy this part of the code).

I would also rather use WaitAll and not use lock.

0
Sep 15 '10 at 17:38
source share



All Articles