C# 获取URL';状态号的适当并发方法;s
我试图了解可用的并发方法,并试图知道哪种方法更适合我当前的场景。我的工作是获取URL列表的状态,无论它们同时返回HTTPStatusC# 获取URL';状态号的适当并发方法;s,c#,C#,我试图了解可用的并发方法,并试图知道哪种方法更适合我当前的场景。我的工作是获取URL列表的状态,无论它们同时返回HTTPStatusOK还是Not OK,限制线程数,并确保提供的最大线程始终运行,而不考虑逐批线程执行。为此,我尝试使用任务并行库,效果很好 代码 var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = 3 }; Parallel.ForEach(ListMonitorUrl, par
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操作完成的问题,因为异步可以在不期望结果的情况下处理吗??