Asp.net 对HTTP处理程序的同时请求不起作用

Asp.net 对HTTP处理程序的同时请求不起作用,asp.net,iis,iis-7,httphandler,Asp.net,Iis,Iis 7,Httphandler,我的ASP.Net应用程序中有一个通用HTTP处理程序(*.ashx),它执行一些基本但耗时的计算,将进度语句打印到输出中,以随时通知用户。执行这些计算需要读取处理程序在使用时锁定的一些数据文件,因此对处理程序的两个调用不能同时开始处理,这一点很重要 为了实现这一点,我在缓存中添加了一个变量,表示计算正在进行中,这可以防止主应用程序在其他用户已经存在的情况下向该处理程序发送用户。在处理程序本身中,它检查是否设置了缓存变量,如果设置了缓存值,则应将用户发送回主应用程序。但是,当我通过两次访问处理程

我的ASP.Net应用程序中有一个通用HTTP处理程序(*.ashx),它执行一些基本但耗时的计算,将进度语句打印到输出中,以随时通知用户。执行这些计算需要读取处理程序在使用时锁定的一些数据文件,因此对处理程序的两个调用不能同时开始处理,这一点很重要

为了实现这一点,我在缓存中添加了一个变量,表示计算正在进行中,这可以防止主应用程序在其他用户已经存在的情况下向该处理程序发送用户。在处理程序本身中,它检查是否设置了缓存变量,如果设置了缓存值,则应将用户发送回主应用程序。但是,当我通过两次访问处理程序来测试这一点时,一次访问执行得很好,而第二次访问在第一次访问运行完成之前什么也不做。将IsReusable设置为true没有区别

有人知道为什么会这样吗

代码如下:

public class UpdateStats : IHttpHandler
{
    private HttpContext _context;

    public const String UpdateInProgressCacheKey = "FAHLeagueWebUpdateInProgress";

    public void ProcessRequest(HttpContext context)
    {
        //Use a Cache variable to ensure we don't call multiple updates
        Object inprogress = context.Cache[UpdateInProgressCacheKey];
        if (inprogress != null)
        {
            //Already updating
            context.Response.Redirect("Default.aspx");
        }
        else
        {
            //Set the Cache variable so we know an Update is happening
            context.Cache.Insert(UpdateInProgressCacheKey, true, null, DateTime.Now.AddMinutes(10), Cache.NoSlidingExpiration);
        }

        context.Response.Clear();
        context.Response.ContentType = "text/html";
        this._context = context;

        context.Response.Write("<pre>Please wait while we Update our Statistics, you will be automatically redirected when this finishes...\n\n");

        //Get the Stats
        Statistics stats = new Statistics(context.Server);

        //Subscribe to Update Progress Events
        stats.UpdateProgress += this.HandleUpdateProgress;

        //Update
        String force = context.Request.QueryString["force"];
        stats.UpdateStats((force != null));

        //Remove the Cache variable
        context.Cache.Remove(UpdateInProgressCacheKey);

        context.Response.Write("</pre>");
        context.Response.Write("<meta http-equiv=\"refresh\" content=\"0;URL=Default.aspx\" />");
        context.Response.Write("<p>If you are not automatically redirected please click <a href=\"Default.aspx\">here</a></p>");
    }

    private void HandleUpdateProgress(String message)
    {
        this._context.Response.Write(message + "\n");
        this._context.Response.Flush();
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

如果两个线程都在其中一个线程设置缓存值之前读取了缓存值inprogress,那么在这两种情况下inprogress都将为null


我认为您可能需要一些锁定,因为上面的代码可能存在一些并发问题。

您确定您的Web服务器是多线程的,并且可以同时执行页面吗?你能在ProcessRequest的开头和结尾添加print语句吗?看看你是否能同时进入其中?

我自己偶然发现了答案,这与web服务器或应用程序无关,而仅仅与浏览器行为有关。如果在Firefox或Chrome等浏览器中打开多个选项卡并导航到同一URL,则浏览器会按顺序发出请求,也就是说,在发出下一个请求之前,它会等待一个请求完成。打开两个浏览器并发出两个请求将导致预期的行为


我想这可能会发生,但这只会导致主应用程序将请求重定向回处理程序,因为如果更新没有发生,则主应用程序仍将需要更新。我认为,如果两个线程都具有空缓存,则意味着您可以点击context.cache.Insert两次,所以你不会阻止第二个请求。但这不是你所描述的问题。行“if(inprogress!=null)this.Response.Redirect(“UpdateStats.ashx”);”也可能存在类似的计时问题,因为这将不得不往返返回浏览器以重定向到处理程序。你是如何提出你的两个测试请求的?它在同一个浏览器中吗?当使用VS2008进行调试时,第二个请求在第一个完成之前甚至不会进入ProcessRequest方法。我在Windows Server 2008上的四核开发箱上运行IIS7,所以我读得很重。这不是因为您的CPU或操作系统是多线程的,而是因为您的Web服务器是多线程的。由于第二个请求在第一个完成之前没有进入ProcessRequest方法,很明显,服务器会按顺序处理请求。这是服务器应用程序的一个限制,也许它可以配置,我没有这方面的经验。您可以尝试查看它在两个不同页面上同时请求时的行为,可能顺序处理只发生在每个页面上。这也意味着你的进程机制目前是“无用的”。
public partial class FAH : System.Web.UI.MasterPage
{
    private Statistics _stats;

    protected void Page_Init(object sender, EventArgs e)
    {
        this._stats = new Statistics(this.Server);
        if (this._stats.StatsUpdateNeeded)
        {
            //If the Cache variable is set we're already updating
            Object inprogress = Cache[UpdateStats.UpdateInProgressCacheKey];
            if (inprogress != null) this.Response.Redirect("UpdateStats.ashx");
        }
    }
    //etc...
}