首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有list的ThreadPool QueueUserWorkItem

带有list的ThreadPool QueueUserWorkItem
EN

Stack Overflow用户
提问于 2010-09-15 17:23:14
回答 2查看 2.2K关注 0票数 1

我想使用来自QueueUserWorkItem的ThreadPool。当我使用下面的代码时,一切都很好。

代码语言:javascript
复制
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();
                }
}

但是,当我使用list代替单个方法调用时,我的程序就会毫无例外地崩溃。

代码语言:javascript
复制
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结合使用。以下是完整的代码:

代码语言:javascript
复制
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();
            }
        }

谢谢

EN

回答 2

Stack Overflow用户

发布于 2010-09-15 17:49:35

您将在工作项排队之后立即释放WaitHandle。主线程中对Dispose的调用与工作线程中的Set之间存在竞争。可能还有其他问题,但很难猜测,因为代码是不完整的。

下面是模式的工作原理。

代码语言:javascript
复制
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中获得,也可以作为反应性扩展下载的一部分。

票数 2
EN

Stack Overflow用户

发布于 2010-09-15 17:38:01

正如汉斯所指出的,目前还不清楚“我”是从哪里来的。但是,我还可以看到您的处理块正在运行和处理,因为您没有在其上使用WaitOne (或者您没有复制代码的那一部分)。

另外,我更喜欢使用WaitAll,而不是使用互锁。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3720111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档