Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取URL';状态号的适当并发方法;s_C# - Fatal编程技术网

C# 获取URL';状态号的适当并发方法;s

C# 获取URL';状态号的适当并发方法;s,c#,C#,我试图了解可用的并发方法,并试图知道哪种方法更适合我当前的场景。我的工作是获取URL列表的状态,无论它们同时返回HTTPStatusOK还是Not OK,限制线程数,并确保提供的最大线程始终运行,而不考虑逐批线程执行。为此,我尝试使用任务并行库,效果很好 代码 var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 3 }; Parallel.ForEach(ListMonitorUrl, par

我试图了解可用的并发方法,并试图知道哪种方法更适合我当前的场景。我的工作是获取URL列表的状态,无论它们同时返回HTTPStatus
OK
还是
Not OK
,限制线程数,并确保提供的最大线程始终运行,而不考虑逐批线程执行。为此,我尝试使用任务并行库,效果很好

代码

 var parallelOptions = new ParallelOptions
 {
     MaxDegreeOfParallelism = 3
 };
 Parallel.ForEach(ListMonitorUrl, parallelOptions, i =>
 {
     LogMailError("URL: " + i.URL + " DateTime: " + DateTime.Now + " Thread ID: " + Thread.CurrentThread.ManagedThreadId, LogFile);
     VerifyWebAppUrl(i);
 });

  public MonitorURLs VerifyWebAppUrl(MonitorURLs Model)
  {
      List<string> UrlsWithNotOKResponse = new List<string>();

      try
      {
          var request = (HttpWebRequest)WebRequest.Create(Model.URL);
          using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
          {
              if (response.StatusCode != HttpStatusCode.OK && Model.Status == "A")
                  Model.ChangeOfStatus = true;
              if (response.StatusCode == HttpStatusCode.OK && Model.Status != "A")
                  Model.ChangeOfStatus = true;
          }
      }
      catch (Exception ex)
      {
          Model.ChangeOfStatus = false;
      }
      return Model;
  }
public async List<Model> GetDeadUrls(List<Model> models)
{
   var action = new ActionBlock<Model>(

      // your async method
      model => VerifyWebAppUrl(model),

      //some options
      new ExecutionDataflowBlockOptions()
      {
         // CancellationToken = sometoken,
         // pick as many as your system can handle
         MaxDegreeOfParallelism = 100,

         // doesn't need to be ordered 
         EnsureOrdered = false,

         // slight performance tweak, there is only one
         SingleProducerConstrained = true  
      });
   
   // start
   foreach (var model in models)
      action.Post(model);
   
   // mark it as completed
   action.Complete();

   // wait for it to finish
   await action.Completion;

   // filter the results
   return models.Where(x => x.ChangeOfStatus).ToList();

}
var parallelOptions=新的parallelOptions
{
MaxDegreeOfParallelism=3
};
ForEach(ListMonitorUrl,parallelOptions,i=>
{
LogMailError(“URL:+i.URL+”DateTime:+DateTime.Now+”线程ID:+Thread.CurrentThread.ManagedThreadId,日志文件);
验证webappurl(i);
});
公共监控器URL验证WebAppURL(监控器URL模型)
{
List UrlsWithNotOKResponse=新列表();
尝试
{
var request=(HttpWebRequest)WebRequest.Create(Model.URL);
使用(HttpWebResponse=(HttpWebResponse)request.GetResponse())
{
if(response.StatusCode!=HttpStatusCode.OK&&Model.Status==“A”)
Model.ChangeOfStatus=true;
if(response.StatusCode==HttpStatusCode.OK&&Model.Status!=“A”)
Model.ChangeOfStatus=true;
}
}
捕获(例外情况除外)
{
Model.ChangeOfStatus=false;
}
收益模型;
}

我也看到过其他方法,比如
SemaphoreSlim
Task
。但我不确定哪一个最适合我的场景。请建议。

并行。ForEach
完全不适合IO绑定的工作负载,您正在耗尽等待IO完成端口的宝贵资源,并限制默认任务调度程序/线程池(这不仅会造成不必要的瓶颈,还会使应用程序的其他部分陷入饥饿)

正确的方法将是支持异步等待模式的东西,比如
Task.whalll
、反应式扩展、TPL数据流等

下面是一个简单的Microsoft TPL数据流示例。你可以在这里找到裸体

优点是:

  • 它采用异步等待模式,开箱即用
  • 您可以控制最大并行度,选择您的系统/应用程序可以处理的最大并行度(这将比
    Parallel.ForEach
    大得多)
  • 它很容易使用
  • 准备就绪后,可以创建更复杂的处理管道
  • 您将不会限制线程池,并且将更加高效和高性能
  • 示例

     var parallelOptions = new ParallelOptions
     {
         MaxDegreeOfParallelism = 3
     };
     Parallel.ForEach(ListMonitorUrl, parallelOptions, i =>
     {
         LogMailError("URL: " + i.URL + " DateTime: " + DateTime.Now + " Thread ID: " + Thread.CurrentThread.ManagedThreadId, LogFile);
         VerifyWebAppUrl(i);
     });
    
      public MonitorURLs VerifyWebAppUrl(MonitorURLs Model)
      {
          List<string> UrlsWithNotOKResponse = new List<string>();
    
          try
          {
              var request = (HttpWebRequest)WebRequest.Create(Model.URL);
              using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
              {
                  if (response.StatusCode != HttpStatusCode.OK && Model.Status == "A")
                      Model.ChangeOfStatus = true;
                  if (response.StatusCode == HttpStatusCode.OK && Model.Status != "A")
                      Model.ChangeOfStatus = true;
              }
          }
          catch (Exception ex)
          {
              Model.ChangeOfStatus = false;
          }
          return Model;
      }
    
    public async List<Model> GetDeadUrls(List<Model> models)
    {
       var action = new ActionBlock<Model>(
    
          // your async method
          model => VerifyWebAppUrl(model),
    
          //some options
          new ExecutionDataflowBlockOptions()
          {
             // CancellationToken = sometoken,
             // pick as many as your system can handle
             MaxDegreeOfParallelism = 100,
    
             // doesn't need to be ordered 
             EnsureOrdered = false,
    
             // slight performance tweak, there is only one
             SingleProducerConstrained = true  
          });
       
       // start
       foreach (var model in models)
          action.Post(model);
       
       // mark it as completed
       action.Complete();
    
       // wait for it to finish
       await action.Completion;
    
       // filter the results
       return models.Where(x => x.ChangeOfStatus).ToList();
    
    }
    
    公共异步列表GetDeadUrls(列表模型)
    {
    var action=newactionblock(
    //您的异步方法
    模型=>VerifyWebAppUrl(模型),
    //一些选择
    新的ExecutionDataflowBlockOptions()
    {
    //CancellationToken=sometoken,
    //选择系统能够处理的尽可能多的数据
    MaxDegreeOfParallelism=100,
    //不需要订购
    重新排序=错误,
    //轻微的性能调整,只有一个
    SingleProducerConstrained=true
    });
    //开始
    foreach(模型中的var模型)
    行动.员额(示范);
    //将其标记为已完成
    动作。完成();
    //等它结束
    等待行动。完成;
    //过滤结果
    返回models.Where(x=>x.ChangeOfStatus.ToList();
    }
    
    异步方法

    public async Task<Model> VerifyWebAppUrl(Model model)
    {
       try
       {
          var request = (HttpWebRequest)WebRequest.Create(model.URL);
          using (var response = (HttpWebResponse) await request.GetResponseAsync())
          {
             if (response.StatusCode != HttpStatusCode.OK && model.Status == "A")
                model.ChangeOfStatus = true;
             if (response.StatusCode == HttpStatusCode.OK && model.Status != "A")
                model.ChangeOfStatus = true;
          }
       }
       catch (Exception ex)
       {
          // this looks suspicious
          model.ChangeOfStatus = false;
       }
       return model;
    }
    
    公共异步任务VerifyWebAppUrl(模型)
    {
    尝试
    {
    var request=(HttpWebRequest)WebRequest.Create(model.URL);
    使用(var response=(HttpWebResponse)wait request.GetResponseAsync())
    {
    if(response.StatusCode!=HttpStatusCode.OK&&model.Status==“A”)
    model.ChangeOfStatus=true;
    if(response.StatusCode==HttpStatusCode.OK&&model.Status!=“A”)
    model.ChangeOfStatus=true;
    }
    }
    捕获(例外情况除外)
    {
    //这看起来可疑
    model.ChangeOfStatus=false;
    }
    收益模型;
    }
    

    注意:这是完全未经测试的,只有一个示例

    “请建议”问题更适合我现在可以理解I/O绑定和CPU绑定操作之间的区别。使用Parallel.Foreach进行异步操作怎么样??这难道不能解决线程等待I/O操作完成的问题,因为异步可以在不期望结果的情况下处理吗??