2010-09-15 99 views
1

我想从ThreadPool中使用QueueUserWorkItem。当我使用下面的代码时,一切正常。ThreadPool QueueUserWorkItem with list

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(); 
       } 
} 

但是,当我使用列表而不是单个方法调用,然后我的程序崩溃没有例外。

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)); 
} 
} 

我错了什么?我应该改变什么?

更新

对不起,我做了在代码中的错误。我在VS2010中使用.NET 2.0。 下面是完整的代码:

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(); 
      } 
     } 

感谢

+1

非常不清楚,“我”的价值应该从哪里来? – 2010-09-15 17:29:27

+0

如果这是C#,则省略号不是允许的参数。因此,为了更好地解决此问题,我们需要知道您为'FillReportingData'声明的参数类型。另外,在示例2中,您仍然只传递一个“LBReportingData”对象,而不是整个列表。 – 2010-09-15 17:31:21

回答

0

正如汉斯指出,目前尚不清楚其中“i”是从哪里来的。但是我也可以看到你的配置块出去了,因为你没有使用WaitOne(或者你没有复制那部分代码)。

另外我宁愿使用WaitAll而不使用互锁。

+0

在这种特殊情况下'WaitAll'会很好,但是它在高容量时确实存在限制。 – James 2010-09-15 17:46:43

2

您在排队工作项目后立即处置WaitHandle。主线程中的Dispose和工作线程中的Set之间存在竞争。可能还有其他问题,但由于代码不完整,难以猜测。

下面是该模式如何工作。

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(); 
} 

该代码使用CountdownEvent类。它可用于.NET 4.0或作为Reactive Extensions下载的一部分。

+0

+1处理AutoResetEvent是我看到的第一个红旗,但是,如果没有完整的代码,很难准确定位它,但我坚决认为这是整体问题的一部分。 – James 2010-09-15 18:06:51