【问题标题】:ThreadPool QueueUserWorkItem with list带有列表的 ThreadPool QueueUserWorkItem
【发布时间】:2010-09-15 17:23:14
【问题描述】:

我想使用 ThreadPool 中的 QueueUserWorkItem。当我使用以下代码时,一切正常。

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

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

更新

抱歉,我的代码有误。我使用 .NET 2.0 和 VS2010。 这是完整的代码:

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

谢谢

【问题讨论】:

  • 很不清楚,“i”的值应该从哪里来?
  • 如果这是 C#,省略号不是允许的参数。因此,为了更好地解决此问题,我们需要知道您为FillReportingData 声明的参数类型。此外,在示例 2 中,您仍然只传递了一个 LBReportingData 对象,而不是整个列表。

标签: c# multithreading threadpool


【解决方案1】:

您将在对工作项进行排队后立即处理 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 下载的一部分提供。

【讨论】:

  • +1 AutoResetEvent 的处理是我看到的第一个危险信号,但是,如果没有完整的代码,很难准确定位它,但我坚持认为这是整体问题的一部分.
【解决方案2】:

正如 Hans 所指出的,“i”的来源尚不清楚。但我也可以看到你的处理块出去并被处理了,因为你没有在上面使用 WaitOne(或者你没有复制那部分代码)。

另外我更喜欢使用 WaitAll 而不是使用 interlocked。

【讨论】:

  • WaitAll 在这种特殊情况下会很好,但是,它在更高容量时确实有其局限性。
猜你喜欢
  • 1970-01-01
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 2014-11-06
  • 2014-06-17
  • 2017-10-16
  • 1970-01-01
相关资源
最近更新 更多