C# 我的线程池有什么问题?

C# 我的线程池有什么问题?,c#,multithreading,C#,Multithreading,我每天都要从远程web服务收集报告我的代码如下: public static void ProcessEnMasse(System.DateTime fromDate, DateTime endDate) { System.Threading.ThreadPool.SetMaxThreads(10, 10); for (System.DateTime d = fromDate; d <= endDate; d = d.AddDays(1))

我每天都要从远程web服务收集报告我的代码如下:

    public static void ProcessEnMasse(System.DateTime fromDate, DateTime endDate)
    {
        System.Threading.ThreadPool.SetMaxThreads(10, 10);
        for (System.DateTime d = fromDate; d <= endDate; d = d.AddDays(1))
        {
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(day => ProcessOneDay(d)));
        }
    }

    public static void ProcessOneDay(System.DateTime theDate)
    {
        Log.Debug(string.Format("Processing {0:yyyy-MM-dd}...", theDate));
        var thePackager = new DataPackager();
        thePackager.CreateDatabaseImportPackage(theDate, theDate, true, false);
    }
publicstaticvoidprocessenmasse(System.DateTime fromDate,DateTime endDate)
{
System.Threading.ThreadPool.SetMaxThreads(10,10);
对于(System.DateTime d=fromDate;d ProcessOneDay(d));
}
}
公共静态无效进程一天(System.DateTime日期)
{
Log.Debug(string.Format(“处理{0:yyyy-MM-dd}…”,theDate));
var thePackager=newdatapackager();
Packager.CreateDatabaseImportPackage(日期、日期、真、假);
}

。。。当我查看日志时,我注意到几个线程正在处理相同的日期。这是为什么?我需要做什么来防止这种情况发生?

所有lambda表达式共享相同的
d
变量

如果其中一个工作项仅在初始线程运行
d=d.AddDays(1)
之后启动,则它将使用该日期


要解决这个问题,请在循环体中声明一个单独的局部变量,并使用它。

您需要注意闭包(我将很快给出更全面的解释)

基本上,您的代码应该是:

public static void ProcessEnMasse(System.DateTime fromDate, DateTime endDate)
    {
        System.Threading.ThreadPool.SetMaxThreads(10, 10);
        for (System.DateTime d = fromDate; d <= endDate; d = d.AddDays(1))
        {
            System.DateTime newD = d;
            System.Threading.ThreadPool.QueueUserWorkItem
                (new System.Threading.WaitCallback(day => ProcessOneDay(newD)));
        }
    }
publicstaticvoidprocessenmasse(System.DateTime fromDate,DateTime endDate)
{
System.Threading.ThreadPool.SetMaxThreads(10,10);
for(System.DateTime d=fromDate;d ProcessOneDay(newD));
}
}

高级思想是(在您的原始代码中),当您传入
d
时,它实际上会捕获该变量,编译后的代码将使该变量起作用,就像它是一个全局共享变量一样。因此,当您点击下一个
for
步骤时,
d
不仅在您的循环中更新,而且在您刚刚传递给它的函数中更新

这是很高的水平,但我真的主张阅读乔恩·斯基特的文章,因为它写得很好

如果您正在寻找更多:)

您就是“”

要解决这个问题:

for (System.DateTime d = fromDate; d <= endDate; d = d.AddDays(1))
{
     DateTime copy = d;
     System.Threading.ThreadPool.QueueUserWorkItem(
            new System.Threading.WaitCallback(day => ProcessOneDay(copy)));
}

关于修复-这是变量“closure”@Reddog,我会看看我是否能找到这篇文章,但我非常确定,要么在5.0中,要么可能只是计划在以后的下一个版本中,但foreach不会执行此操作same@JustinPihony:是;Eric Lippert说这是在5年内修复的。(但对于
foreach
,而不是
for
)非常好。我知道这一定很简单。我不经常使用线程,线程池也不经常使用,所以这绝对是一个“好消息”。我将此标记为答案,因为它是最完整的。感谢大家对问题的快速准确诊断。
for (System.DateTime d = fromDate; d <= endDate; d = d.AddDays(1))
{         
     ThreadPool.QueueUserWorkItem(day => ProcessOneDay((DateTime) day), d);
}