are there any drawbacks or risks of using Parallel.Foreach with WebClient() inside my asp.net mvc web application

后端 未结 2 1027
囚心锁ツ
囚心锁ツ 2021-02-11 03:21

I am working on an asp.net MVC-5 web application, and based on some articles i read that i should not use Parallel methods inside web servers and inside .net web applications es

相关标签:
2条回答
  • 2021-02-11 03:40

    Take a look at:
    object syncObj = new object();
    lock(syncObj)

    try
    {
        using (WebClient wc = new WebClient()) 
        {
            string url = currentURL + "resources?AUTHTOKEN=" + pmtoken;
            var json = await wc.DownloadStringTaskAsync(url);
            resourcesinfo = JsonConvert.DeserializeObject<ResourcesInfo>(json);
        }
    
        object syncObj = new object();  // create sync object
        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);
            }
    
            lock(syncObj)  // lock using sync object
            {
                PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);
            }
        });//end of foreach
    
        return PMresourcesOnly.ToList();
    }
    catch (Exception e)
    {
    }
    
    0 讨论(0)
  • 2021-02-11 03:47

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

    No, you absolutely should avoid using parallel methods inside ASP.NET apps.

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

    Parallel is for data parallism (running the same CPU-bound code over a collection of data items). StartNew is for dynamic task parallelism (running the same or different CPU-bound code over a collection of items that changes as you process it).

    Neither approach is appropriate here, since the work you have to do is I/O-bound, not CPU-bound.

    What you actually want is concurrency (doing multiple things at a time), not parallelism. Instead of using parallel concurrency (doing multiple things at a time by using multiple threads), what you want is asynchronous concurrency (doing multiple things at a time using no threads).

    Asynchronous concurrency is possible in code via await Task.WhenAll, as such:

    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.
    }
    

    As a final note, you may want to look into HttpClient, which was designed for asynchronous operations and has the nice property that you only need one of them for any number of simultaneous calls.

    0 讨论(0)
提交回复
热议问题