![](/img/trans.png)
[英]How to implement queue mechanism in ASP.Net Core 2.1 with AWS
[英]How to implement a queue on a IHttpHandler in a ASP.NET Web app?
我有一個ASP.NET Web應用程序,該應用程序具有IHttpHandler
來處理POST
請求(基本上,它將處理JSON,然后將處理結果發送回客戶端)。
我想在我的應用程序中實現一個隊列系統,這樣,如果存在類似的發布請求,則不會並行處理它們,而是一個接一個地處理。
問題 :
Queue
對象? 我無法在Page_Load()
事件中聲明Queue,因為在打開網頁時不會發送請求。 我需要隊列始終等待傳入的POST請求。 如果我在IHttpHandler中聲明了隊列,則每次POST請求到來時該隊列都會重置。
謝謝 !
實現此目的的一種方法是改為使用IHttpAsyncHandler和單例服務類。 輔助線程等待新項目添加到ConcurrentQueue的BlockingCollection中。 這將啟用傳入請求的串行處理。 需要在處理第一個請求之前啟動服務類中的工作線程,可以從全局Application_Start例程或通過將PreApplicationStartMethod添加到AssembleInfo.cs文件中來調用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;
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.