C# 如何在ASP.NET Web应用程序中的IHttpHandler上实现队列?

C# 如何在ASP.NET Web应用程序中的IHttpHandler上实现队列?,c#,asp.net,post,queue,httphandler,C#,Asp.net,Post,Queue,Httphandler,我有一个ASP.NET web应用程序,它有一个IHttpHandler来处理POST请求(基本上,它将处理JSON,然后将处理结果发送回客户端) 我想在我的应用程序中实现一个队列系统,这样如果有模拟的post请求,它们不会被并行处理,而是一个接一个地处理 问题: 实现这一目标的最佳方式是什么 我应该在应用程序中的何处声明队列对象 我如何附加一个特定的函数(将进行处理的函数),以便在每次执行项目时执行 是否已添加到队列中 我无法在Page\u Load()事件中声明队列,因为打开网页时不会发送请

我有一个ASP.NET web应用程序,它有一个
IHttpHandler
来处理
POST
请求(基本上,它将处理JSON,然后将处理结果发送回客户端)

我想在我的应用程序中实现一个队列系统,这样如果有模拟的post请求,它们不会被并行处理,而是一个接一个地处理

问题

  • 实现这一目标的最佳方式是什么
  • 我应该在应用程序中的何处声明
    队列
    对象
  • 我如何附加一个特定的函数(将进行处理的函数),以便在每次执行项目时执行 是否已添加到队列中
  • 我无法在
    Page\u Load()
    事件中声明队列,因为打开网页时不会发送请求。我需要队列始终等待传入的POST请求。如果我在IHttpHandler中声明了队列,那么每次POST请求到来时,队列都会重置


    谢谢

    实现这一点的一种方法是使用IHTTPassynchandler和单例服务类。工作线程等待新项目添加到ConcurrentQueue的BlockingCollection。这将启用对传入请求的串行处理。服务类中的工作线程需要在处理第一个请求之前启动,可以从全局应用程序启动例程或通过向AssembleInfo.cs文件添加PreApplicationStartMethod来调用start方法

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Web;
    
    namespace webgateway
    {
        public class RequestHandler : IHttpAsyncHandler, IDisposable
        {
    
    
            public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
            {
    
                RequestContext requestContext = new RequestContext(cb, context, extraData);
    
                Service.Instance.QueueRequest(requestContext);
    
                return requestContext;
    
            }
    
    
            //Start could be called from the Global asax or by adding this attribute to the Assembly.cs 
            //[assembly: PreApplicationStartMethod(typeof(webgateway.RequestHandler), "Start")]
            public static void Start()
            {
    
                Service.Instance.Start();
            } 
    
            public void EndProcessRequest(IAsyncResult result) {
            }
            public bool IsReusable { get { return true; } }
            public void ProcessRequest(HttpContext context) { }
            public void Dispose() { }
        }
    
    }
    
    
    public sealed class Service
    {
    
        private static readonly Service _Instance = new Service();
        public static Service Instance
        {
            get { return _Instance; }
        }
        private Service()
        {
        }
    
    
        private static bool _running = false;
    
        private BlockingCollection<RequestContext> blockingQueue = new BlockingCollection<RequestContext>(new ConcurrentQueue<RequestContext>());
    
    
        public void Start()
        {
            _running = true;
            ThreadPool.QueueUserWorkItem(worker, null);
    
        }
    
        private void worker(object state)
        {
    
            RequestContext requestContext;
    
            while (_running)
            {
    
                //Block until a new item is added to the queue
                if (blockingQueue.TryTake(out requestContext, 10000))
                {
    
                    //You could delegate the work to another function , class , library or process inline here... 
    
                    //Simulate a random delay 
                    Thread.Sleep((new Random()).Next(1000, 5000));
    
    
                    //Make sure the client is connected before sending the response 
                    if (requestContext.HttpContext.Response.IsClientConnected)
                    {
                        requestContext.HttpContext.Response.BufferOutput = false;
                        requestContext.HttpContext.Response.ContentType = "text/plain";
                        requestContext.HttpContext.Response.Write(requestContext.HttpContext.Request["echo"]);
                        requestContext.HttpContext.Response.Flush();
                        requestContext.CompleteCall();
                    }
    
                }
    
            }
    
        }
    
        public void Stop()
        {
            _running = false;
        }
    
        public void QueueRequest(RequestContext requestContext)
        {
    
            if (!blockingQueue.TryAdd(requestContext))
            {
                //handle error 
            }
        }
    
    }
    
    public class RequestContext : IAsyncResult
    {
    
        private ManualResetEvent _event;
        private object _lock = new Object();
        private AsyncCallback _callback;
        private HttpContext _httpContext;
        private bool _completed;
        private bool _completedSynchronously;
        private object _state;
    
        public RequestContext(AsyncCallback cb, HttpContext hc, object state)
        {
            _callback = cb;
            _httpContext = hc;
            _completedSynchronously = false;
            _completed = false;
            _state = state;
        }
    
        public HttpContext HttpContext
        {
            get { return _httpContext; }
        }
    
        public void CompleteCall()
        {
            lock (_lock)
            {
                _completed = true;
                if (_event != null)
                {
                    _event.Set();
                }
            }
    
            _callback?.Invoke(this);
        }
    
        public bool IsCompleted
        {
            get { return _completed; }
        }
    
        public bool CompletedSynchronously
        {
            get { return _completedSynchronously; }
        }
    
        public object AsyncState
        {
            get { return _state; }
        }
    
        public WaitHandle AsyncWaitHandle
        {
            get
            {
                lock (_lock)
                {
    
                    if (_event == null)
                    {
                        _event = new ManualResetEvent(IsCompleted);
                    }
                    return _event;
                }
            }
        }
    
    }
    
    使用系统;
    使用System.Collections.Concurrent;
    使用系统线程;
    使用System.Web;
    命名空间webgateway
    {
    公共类RequestHandler:IHTTPassynchandler,IDisposable
    {
    公共IAsyncResult BeginProcessRequest(HttpContext上下文、AsyncCallback cb、object extraData)
    {
    RequestContext RequestContext=新的RequestContext(cb、context、extraData);
    Service.Instance.QueueRequest(requestContext);
    返回请求上下文;
    }
    //可以从全局asax或通过将此属性添加到Assembly.cs来调用Start
    //[assembly:PreApplicationStartMethod(typeof(webgateway.RequestHandler),“Start”)]
    公共静态void Start()
    {
    Service.Instance.Start();
    } 
    公共无效EndProcessRequest(IAsyncResult结果){
    }
    公共布尔可重用{get{return true;}}
    公共void ProcessRequest(HttpContext上下文){}
    public void Dispose(){}
    }
    }
    公共密封类服务
    {
    私有静态只读服务_Instance=new Service();
    公共静态服务实例
    {
    获取{return\u Instance;}
    }
    私人服务()
    {
    }
    私有静态bool_running=false;
    private BlockingCollection blockingQueue=new BlockingCollection(new ConcurrentQueue());
    公开作废开始()
    {
    _运行=真;
    ThreadPool.QueueUserWorkItem(worker,null);
    }
    私有无效工作程序(对象状态)
    {
    请求上下文请求上下文;
    当(_运行时)
    {
    //阻止,直到将新项目添加到队列中
    if(blockingQueue.TryTake(out-requestContext,10000))
    {
    //您可以在此处将工作委托给另一个函数、类、库或内联进程。。。
    //模拟随机延迟
    Sleep((new Random()).Next(10005000));
    //在发送响应之前,确保客户端已连接
    if(requestContext.HttpContext.Response.IsClient已连接)
    {
    requestContext.HttpContext.Response.BufferOutput=false;
    requestContext.HttpContext.Response.ContentType=“text/plain”;
    requestContext.HttpContext.Response.Write(requestContext.HttpContext.Request[“echo”]);
    requestContext.HttpContext.Response.Flush();
    requestContext.CompleteCall();
    }
    }
    }
    }
    公共停车场()
    {
    _运行=错误;
    }
    公共无效队列请求(RequestContext RequestContext)
    {
    如果(!blockingQueue.TryAdd(requestContext))
    {
    //处理错误
    }
    }
    }
    公共类RequestContext:IAsyncResult
    {
    私人手动复位事件_事件;
    私有对象_lock=新对象();
    私有异步回调\u回调;
    私有HttpContextu HttpContext;
    私人住宅竣工;
    私有布尔同步完成;
    私有对象状态;
    公共请求上下文(异步回调cb、HttpContext hc、对象状态)
    {
    _回调=cb;
    _httpContext=hc;
    _completedSynchronously=false;
    _完成=错误;
    _状态=状态;
    }
    公共HttpContext HttpContext
    {
    获取{return\u httpContext;}
    }
    公共void CompleteCall()
    {
    锁
    {
    _完成=正确;
    如果(_事件!=null)
    {
    _event.Set();
    }
    }
    _回调?调用(这个);
    }
    公共图书馆完工了
    {
    获取{return\u completed;}
    }
    公共布尔同步完成
    {
    获取{return\u completedSynchronously;}
    }
    公共对象异步状态
    {
    获取{return\u state;}
    }
    公共WaitHandle异步WaitHandle
    {
    得到
    {
    锁
    {
    如果(_event==null)
    {
    _事件=新手动重置事件(已完成);
    }
    返回事件;
    }
    }
    }
    }