C# 如何在ASP.NET Web应用程序中的IHttpHandler上实现队列?
我有一个ASP.NET web应用程序,它有一个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()事件中声明队列,因为打开网页时不会发送请
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)
{
_事件=新手动重置事件(已完成);
}
返回事件;
}
}
}
}