C# 最大限度地利用Parallel.For或Parallel.Foreach循环

C# 最大限度地利用Parallel.For或Parallel.Foreach循环,c#,multithreading,performance,parallel-processing,parallel.foreach,C#,Multithreading,Performance,Parallel Processing,Parallel.foreach,在我的小型控制台应用程序中,我有一个嵌套的Parallel.For和PLINQ语句结构,基本上执行网络绑定操作(执行http请求),如下所示: Parallel.For(0,users.count(), index=>{ // here I try to perform HTTP requests for multiple users }); Parallel.For(0,users.count(), index=>{ // Some stuff is done before

在我的小型控制台应用程序中,我有一个嵌套的Parallel.For和PLINQ语句结构,基本上执行网络绑定操作(执行http请求),如下所示:

Parallel.For(0,users.count(), index=>{

// here I try to perform HTTP requests for multiple users

});
Parallel.For(0,users.count(), index=>{

// Some stuff is done before the PLINQ statement is called... 
newFilteredList.AsParallel().WithDegreeOfParallelism(60).ForAll(qqmethod =>
    {
        var xdocic = new XmlDocument();
        xdocic.LoadXml(SendXMLRequestToEbay(null, null, qqmethod.ItemID, true, TotalDaysSinceLastUpdate.ToString(), null));
        int TotalPages = 0;
        if (xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0) != null)
        {
            TotalPages = Convert.ToInt32(xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0).InnerText);
        }
        if (TotalPages > 1)
        {
            for (int i = 1; i < TotalPages + 1; i++)
            {
                Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), i.ToString()));
            }
        }
        else
        {
            Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), "1"));
        }
    });
});
从DB中填写用户列表,然后我执行以下操作:

Parallel.For(0,users.count(), index=>{

// here I try to perform HTTP requests for multiple users

});
Parallel.For(0,users.count(), index=>{

// Some stuff is done before the PLINQ statement is called... 
newFilteredList.AsParallel().WithDegreeOfParallelism(60).ForAll(qqmethod =>
    {
        var xdocic = new XmlDocument();
        xdocic.LoadXml(SendXMLRequestToEbay(null, null, qqmethod.ItemID, true, TotalDaysSinceLastUpdate.ToString(), null));
        int TotalPages = 0;
        if (xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0) != null)
        {
            TotalPages = Convert.ToInt32(xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0).InnerText);
        }
        if (TotalPages > 1)
        {
            for (int i = 1; i < TotalPages + 1; i++)
            {
                Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), i.ToString()));
            }
        }
        else
        {
            Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), "1"));
        }
    });
});
然后在这个for循环中,我执行一个plinq语句,通过HTTP请求获取这个用户的信息

现在我总共得到两个嵌套循环,如下所示:

Parallel.For(0,users.count(), index=>{

// here I try to perform HTTP requests for multiple users

});
Parallel.For(0,users.count(), index=>{

// Some stuff is done before the PLINQ statement is called... 
newFilteredList.AsParallel().WithDegreeOfParallelism(60).ForAll(qqmethod =>
    {
        var xdocic = new XmlDocument();
        xdocic.LoadXml(SendXMLRequestToEbay(null, null, qqmethod.ItemID, true, TotalDaysSinceLastUpdate.ToString(), null));
        int TotalPages = 0;
        if (xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0) != null)
        {
            TotalPages = Convert.ToInt32(xdocic.GetElementsByTagName("TotalNumberOfPages").Item(0).InnerText);
        }
        if (TotalPages > 1)
        {
            for (int i = 1; i < TotalPages + 1; i++)
            {
                Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), i.ToString()));
            }
        }
        else
        {
            Products.Add(SendXMLRequestToEbay(null, null, qqmethod.ItemID, false, TotalDaysSinceLastUpdate.ToString(), "1"));
        }
    });
});
Parallel.For(0,users.count(),index=>{
//在PLINQ语句被调用之前做了一些事情。。。
newFilteredList.AsParallel()。具有DegreeOfParallelism(60).ForAll(qqmethod=>
{
var xdocic=new XmlDocument();
LoadXml(SendXMLRequestToEbay(null,null,qqmethod.ItemID,true,TotalDaysSinceLastUpdate.ToString(),null));
int TotalPages=0;
if(xdoc.GetElementsByTagName(“TotalNumberOfPages”).Item(0)!=null)
{
TotalPages=Convert.ToInt32(xdoc.GetElementsByTagName(“TotalNumberOfPages”).Item(0.InnerText);
}
如果(总页数>1)
{
对于(int i=1;i
我试着像使用常规的for循环一样使用外部for循环,我注意到它的运行速度比这样快得多,也比这样好得多

这里最让我担心的是,我在运行控制台应用程序时检查CPU的利用率,它总是接近总CPU功率的0.5-3%

因此,我尝试执行HTTP请求的方式如下:

一次15个用户*这15个用户的HTTP请求量


我做错了什么?

并行类不适用于非CPU限制的工作。HTTP请求是I/O绑定的。另外,
产品的类型是什么
,如果它只是一个
列表
,那么该类不是线程安全的,并且您在同时使用多个线程写入时正在破坏该类。@ScottChamberlain您建议我用什么替换第一个外部for循环?我希望能够为这些用户处理15个并同时发送15个http请求,我该怎么做?@ScottChamberlain产品是并发包=)相反,您可以在一个链中有两个块,一个用于发送请求,一个用于处理,您可以为每个块设置最大并行度。请参阅,它有两个块,一个并行获取记录,然后一个一次处理一个记录,将其添加到列表中。您可以将第二个块转换为所需的“处理”,并将其设置为比1更高的并行度。