gpt4 book ai didi

c# - 在我的 asp.net mvc web 应用程序中使用 Parallel.Foreach 和 WebClient() 有什么缺点或风险吗

转载 作者:行者123 更新时间:2023-11-30 19:55:15 33 4
gpt4 key购买 nike

我正在开发一个 asp.net MVC-5 web 应用程序,根据我读到的一些文章,我不应该在 web 服务器和 .net web 应用程序中特别使用并行方法。现在在我的例子中,我需要在 foreach 中发出大约 1,500 个 WebClient() 调用,然后反序列化从 WebClient() 调用返回的 json 对象。我在使用 Parallel.Foreach 之前的原始代码如下,大约需要 15 分钟才能完成:-

    public async Task <List<Details2>> Get()
{

try
{

using (WebClient wc = new WebClient())
{
string url = currentURL + "resources?AUTHTOKEN=" + pmtoken;
var json = await wc.DownloadStringTaskAsync(url);
resourcesinfo = JsonConvert.DeserializeObject<ResourcesInfo>(json);

}


ForEach( var c in resourcesinfo.operation.Details)
{

ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
using (WebClient wc = new WebClient())
{

string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
string tempurl = url.Trim();



var json = await wc.DownloadStringTaskAsync(tempurl);
resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);


}

if (resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count > 0)
{
List<CUSTOMFIELD> customfield = resourceAccountListInfo.operation.Details.CUSTOMFIELD.Where(a =>
a.CUSTOMFIELDLABEL.ToLower() == "name"
).ToList();
if (customfield.Count == 1)
{
PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);

}

}

}//end of foreach

return PMresourcesOnly.ToList();

}
catch (Exception e)
{
}
return new List<Details2>();
}

现在我做了以下修改:-

  • 我将 foreach 替换为 Parallel.ForEach
  • 因为我不应该在 Parallel.ForEach 中使用异步方法所以我将 DownloadStringTaskAsync 更改为 DownloadString并行.Foreach :-

    public async Task <List<Details2>> Get()
    {



    try
    {

    using (WebClient wc = new WebClient())
    {
    string url = currentURL + "resources?AUTHTOKEN=" + pmtoken;
    var json = await wc.DownloadStringTaskAsync(url);
    resourcesinfo = JsonConvert.DeserializeObject<ResourcesInfo>(json);

    }


    Parallel.ForEach(resourcesinfo.operation.Details, new ParallelOptions { MaxDegreeOfParallelism = 7 }, (c) =>
    {

    ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
    using (WebClient wc = new WebClient())
    {

    string url = currentURL + "resources/" + c.RESOURCEID + "/accounts?AUTHTOKEN=" + pmtoken;
    string tempurl = url.Trim();



    var json = wc.DownloadString(tempurl);
    resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);


    }

    if (resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count > 0)
    {
    List<CUSTOMFIELD> customfield = resourceAccountListInfo.operation.Details.CUSTOMFIELD.Where(a =>
    a.CUSTOMFIELDLABEL.ToLower() == "name"
    ).ToList();
    if (customfield.Count == 1)
    {
    PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);

    }

    }



    });//end of foreach




    return PMresourcesOnly.ToList();

    }
    catch (Exception e)
    {
    }
    return new List<Details2>();
    }

现在,当我使用 Parallel.Foreach 时,执行时间从 15 分钟减少到大约 7 分钟。但如果我的第二种方法有效,我有点困惑,所以任何人都可以就这些问题(或任何问题)提出建议:-

  1. Parallel.ForeachWebclient() 一起使用是否是一种有效的方法?或者我应该避免在 .net 和 Web 应用程序中使用并行方法?

  2. 当使用 Parallel.Foreach 时,我是否会遇到任何问题,例如 return PMresourcesOnly.ToList(); 返回给客户端,同时仍然有一些 wc.DownloadString(tempurl); 没有完成?

  3. 如果我想比较这两种方法(Parallel.Foreach 和 Foreach),结果是否相同?

  4. 在一些在线文章中,他们使用 Task.Factory.StartNew(() 而不是使用 Parallel.foreach 那么它们之间的主要区别是什么?

编辑我尝试按如下方式定义 SemaphoreSlim:-

public async Task <List<Details2>> Get()
{
SemaphoreSlim throttler = new SemaphoreSlim(initialCount: 15);
try
{
//code goes here

var tasks = resourcesinfo.operation.Details.Select(c => TryDownloadResourceAsync(c.RESOURCEID,throttler)).ToList();
}

///---

private async Task<Details2> TryDownloadResourceAsync(string resourceId, SemaphoreSlim throttler)
{
await throttler.WaitAsync();
try
{
using (WebClient wc = new WebClient()) //get the tag , to check if there is a server with the same name & tag..
{}
}
finally
{
throttler.Release();
}

最佳答案

is using Parallel.Foreach with Webclient() a valid approach to follow ? or i should avoid using Parallel methods inside .net and web applications?

不,您绝对应该避免在 ASP.NET 应用程序中使用并行方法。

on some online articles they use Task.Factory.StartNew(() instead of using Parallel.foreach so what are the main differences between them ?

Parallel 用于 data parallism (在一组数据项上运行相同的 CPU 绑定(bind)代码)。 StartNew 用于 dynamic task parallelism (在处理过程中发生变化的项目集合上运行相同或不同的 CPU 绑定(bind)代码)。

这两种方法都不适合这里,因为您必须做的工作是 I/O 绑定(bind)的,而不是 CPU 绑定(bind)的。

您真正想要的是并发(一次做多件事),而不是并行。不要使用并行并发(通过使用多个线程一次做多件事),您想要的是异步并发(一次不使用线程做多件事)。

通过 await Task.WhenAll 可以在代码中实现异步并发,例如:

private async Task<string> TryDownloadResourceAsync(string resourceId)
{
ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
using (WebClient wc = new WebClient())
{
string url = currentURL + "resources/" + resourceId + "/accounts?AUTHTOKEN=" + pmtoken;
string tempurl = url.Trim();

var json = await wc.DownloadStringTaskAsync(tempurl);
resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
}

if (resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count > 0)
{
List<CUSTOMFIELD> customfield = resourceAccountListInfo.operation.Details.CUSTOMFIELD.Where(a =>
a.CUSTOMFIELDLABEL.ToLower() == "name"
).ToList();
if (customfield.Count == 1)
{
return resourceAccountListInfo.operation.Details;
}
}
return null;
}

public async Task <List<Details2>> Get()
{
try
{
using (WebClient wc = new WebClient())
{
string url = currentURL + "resources?AUTHTOKEN=" + pmtoken;
var json = await wc.DownloadStringTaskAsync(url);
resourcesinfo = JsonConvert.DeserializeObject<ResourcesInfo>(json);
}

var tasks = resourcesinfo.operation.Details.Select(c => TryDownloadResourceAsync(c.RESOURCEID)).ToList();
var results = await Task.WhenAll(tasks).Select(x => x != null);
return results.ToList();
}
catch (Exception e)
{
}
return new List<Details2>(); // Please, please don't do this in production.
}

最后一点,您可能需要查看 HttpClient,它是为异步操作而设计的,并且具有一个很好的属性,即您只需要一个同时通话的数量。

关于c# - 在我的 asp.net mvc web 应用程序中使用 Parallel.Foreach 和 WebClient() 有什么缺点或风险吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38088270/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com