我有一个从远程站点检索html并解析它的进程。我将几个URL传递给方法,因此我希望每次URL完成解析时都会对进程进行ajaxify并发出屏幕通知。例如,这就是我想要做的事情:
List<string> urls = ...//load up with arbitary # of urls
foreach (var url in urls)
{
string html = GetContent(url);
//DO SOMETHING
//COMPLETED.. SEND NOTIFICATION TO SCREEN (HOW DO I DO THIS)
}
public static string GetContent(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
using (var stream = request.GetResponse().GetResponseStream())
{
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
在循环的每次迭代中,我想显示URL已完成并继续下一个。我怎么能做到这一点?
答案 0 :(得分:1)
您需要担心的第一件事是(我假设)您在ASP.NET代码中运行可能长时间运行的操作。当您运行IIS超时时,这将成为一个问题。 (默认情况下,90秒。)假设您正在处理十个网址,每个网址需要15秒才能完成reader.ReadToEnd()
- 您的代码将超时并在第六个网址后被杀死。
你可能会想“我可以加快超时”,但这不是一个好的答案;你还处于时间压力之下。
我解决这类问题的方法是将长时间运行的操作转移到独立的Windows服务中,然后使用WCF在ASP.NET代码和服务之间进行通信。服务可以运行一个线程池,执行处理一组URL的请求。 (Here's an implementation,允许您对工作项进行排队。)
现在,您可以从您的网页通过AJAX请求轮询状态更新。 ASP.NET代码中的处理程序可以使用WCF从服务进程中提取状态信息。
执行此操作的方法可能是为每个提交的工作单元分配唯一ID,并将该ID返回给客户端。然后,客户端可以通过发送工作单元n
状态的AJAX请求来轮询状态。在服务中,保留List
个工作单元及其状态(lock
,以避免并发问题。
public class WorkUnit {
public int ID { get; set; }
public List<string> URLs { get; set; }
public int Processed { get; set; }
}
private var workUnits = new List<WorkUnit>();
private void ExecuteWorkUnit(int id) {
var unit = GetWorkUnit(id);
foreach (var url in unit.URLs) {
string html = GetContent(url);
// do whatever else...
lock (workUnits) unit.Processed++;
}
}
public WorkUnit GetWorkUnit(int id) {
lock (workUnits) {
// Left as an exercise for the reader
}
}
您需要填写方法来添加工作单元,返回给定工作单元的状态,并处理线程池。
我使用了类似的架构并取得了巨大的成功。