C# 具有实时界面进度状态的Ajax服务器进程?
我有一个从远程站点检索html并对其进行解析的过程。我将几个URL传递到该方法中,因此我希望在每次URL完成解析时对该过程进行ajaxify,并给出一个屏幕通知。例如,这就是我试图做的:C# 具有实时界面进度状态的Ajax服务器进程?,c#,.net,asp.net,ajax,asp.net-ajax,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 //COMP
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=…//加载任意的URL
foreach(url中的变量url)
{
字符串html=GetContent(url);
//做点什么
//已完成..向屏幕发送通知(如何执行此操作)
}
公共静态字符串GetContent(字符串url)
{
HttpWebRequest请求=(HttpWebRequest)WebRequest.Create(url);
request.Method=“GET”;
使用(var stream=request.GetResponse().GetResponseStream())
{
使用(var reader=newstreamreader(stream,Encoding.UTF8))
{
返回reader.ReadToEnd();
}
}
}
在循环中的每个迭代中,我希望显示URL已完成,并继续下一个迭代。如何才能做到这一点?您首先需要担心的是(我假设)您正在ASP.NET代码中运行一个可能会长期运行的操作。当您遇到IIS超时时,这将成为一个问题。(默认情况下为90秒。)假设您正在处理10个URL,每个URL需要15秒才能完成
reader.ReadToEnd()
–您的代码将超时,并在第六个URL之后被删除
你可能会想“我可以加快超时时间”,但这不是一个好答案;你仍然面临时间压力
我解决此类问题的方法是将长期运行的操作移动到独立的Windows服务中,然后使用WCF在ASP.NET代码和服务之间进行通信。该服务可以运行线程池,该线程池执行处理一组URL的请求。(允许您对工作项进行排队。)
现在,从您的web页面,您可以通过AJAX请求轮询状态更新。ASP.NET代码中的处理程序可以使用WCF从服务进程中提取状态信息
一种方法是为每个提交的工作单元分配一个唯一的ID,并将该ID返回给客户端。然后,客户端可以通过发送工作单元状态的AJAX请求来轮询状态。在服务中,保留工作单元的列表及其状态(锁定以避免并发问题)
公共类工作单元{
公共int ID{get;set;}
公共列表URL{get;set;}
公共整数处理{get;set;}
}
private var workUnits=new List();
私有void ExecuteWorkUnit(int-id){
var unit=GetWorkUnit(id);
foreach(单位url中的变量url){
字符串html=GetContent(url);
//做任何其他事情。。。
锁定(工作单元)单元。已处理++;
}
}
公共工作单元GetWorkUnit(内部id){
锁(工作单元){
//留给读者作为练习
}
}
您需要填写方法来添加工作单元、返回给定工作单元的状态以及处理线程池
我使用了类似的体系结构,并取得了巨大成功
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
}
}