我想使用来自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();
}
}但是,当我使用list代替单个方法调用时,我的程序就会毫无例外地崩溃。
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();
}
}谢谢
发布于 2010-09-15 17:49:35
您将在工作项排队之后立即释放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中获得,也可以作为反应性扩展下载的一部分。
发布于 2010-09-15 17:38:01
正如汉斯所指出的,目前还不清楚“我”是从哪里来的。但是,我还可以看到您的处理块正在运行和处理,因为您没有在其上使用WaitOne (或者您没有复制代码的那一部分)。
另外,我更喜欢使用WaitAll,而不是使用互锁。
https://stackoverflow.com/questions/3720111
复制相似问题