ThreadPool QueueUserWorkItem со списком - PullRequest
       7

ThreadPool QueueUserWorkItem со списком

1 голос
/ 15 сентября 2010

Я хотел бы использовать QueueUserWorkItem из ThreadPool.Когда я использую следующий код, все работает хорошо.

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

Спасибо

Ответы [ 2 ]

2 голосов
/ 15 сентября 2010

Вы выбрасываете WaitHandle сразу после постановки в очередь рабочих элементов.Между вызовом Dispose в основном потоке и Set в рабочем потоке.Могут быть и другие проблемы, но трудно догадаться, потому что код неполон.

Вот как должен работать шаблон.CountdownEvent класс.Он доступен в .NET 4.0 или как часть Реактивных расширений .

0 голосов
/ 15 сентября 2010

Как указал Ганс, неясно, откуда исходит "я".Но также я вижу, что ваш блок утилизации выходит и удаляется, потому что вы не используете на нем WaitOne (или вы не скопировали эту часть кода).

Также я бы предпочел использовать WaitAll и не использовать блокировку.

...