具有实时接口进度状态的Ajax服务器进程?

时间:2010-10-24 20:32:40

标签: c# .net asp.net ajax asp.net-ajax

我有一个从远程站点检索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已完成并继续下一个。我怎么能做到这一点?

1 个答案:

答案 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
    }
}

您需要填写方法来添加工作单元,返回给定工作单元的状态,并处理线程池。

我使用了类似的架构并取得了巨大的成功。