我正在嘗試向使用異步編程處理圖像的HttpModule添加速度提升。正確使用HttpModule中的ConcurrentQueue?
儘管看起來我正在獲得性能提升,但我想檢查一下我是否使用了正確提供的工具。
我特別擔心我正在處理隊列不正確。
我正在採取的方法。
- 初始化的ConcurrentQueue
- 添加processImage來法隊列上 的BeginEventHandler在AddOnBeginRequestAsync
- 進程隊列上EndEventHandler在 AddOnBeginRequestAsync
有很多的代碼,所以我的道歉,但異步編程很難:
個字段
/// <summary>
/// The thread safe fifo queue.
/// </summary>
private static ConcurrentQueue<Action> imageOperations;
/// <summary>
/// A value indicating whether the application has started.
/// </summary>
private static bool hasAppStarted = false;
HTTP模塊初始化
/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">
/// An <see cref="T:System.Web.HttpApplication"/> that provides
/// access to the methods, properties, and events common to all
/// application objects within an ASP.NET application
/// </param>
public void Init(HttpApplication context)
{
if (!hasAppStarted)
{
lock (SyncRoot)
{
if (!hasAppStarted)
{
imageOperations = new ConcurrentQueue<Action>();
DiskCache.CreateCacheDirectories();
hasAppStarted = true;
}
}
}
context.AddOnBeginRequestAsync(OnBeginAsync, OnEndAsync);
context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders;
}
事件處理程序
/// <summary>
/// The <see cref="T:System.Web.BeginEventHandler"/> that starts
/// asynchronous processing
/// of the <see cref="T:System.Web.HttpApplication.BeginRequest"/>.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">
/// An <see cref="T:System.EventArgs">EventArgs</see> that contains
/// the event data.
/// </param>
/// <param name="cb">
/// The delegate to call when the asynchronous method call is complete.
/// If cb is null, the delegate is not called.
/// </param>
/// <param name="extraData">
/// Any additional data needed to process the request.
/// </param>
/// <returns></returns>
IAsyncResult OnBeginAsync(
object sender, EventArgs e, AsyncCallback cb, object extraData)
{
HttpContext context = ((HttpApplication)sender).Context;
EnqueueDelegate enqueueDelegate = new EnqueueDelegate(Enqueue);
return enqueueDelegate.BeginInvoke(context, cb, extraData);
}
/// <summary>
/// The method that handles asynchronous events such as application events.
/// </summary>
/// <param name="result">
/// The <see cref="T:System.IAsyncResult"/> that is the result of the
/// <see cref="T:System.Web.BeginEventHandler"/> operation.
/// </param>
public void OnEndAsync(IAsyncResult result)
{
// An action to consume the ConcurrentQueue.
Action action =() =>
{
Action op;
while (imageOperations.TryDequeue(out op))
{
op();
}
};
// Start 4 concurrent consuming actions.
Parallel.Invoke(action, action, action, action);
}
委託和對rocess
/// <summary>
/// The delegate void representing the Enqueue method.
/// </summary>
/// <param name="context">
/// the <see cref="T:System.Web.HttpContext">HttpContext</see> object that
/// provides references to the intrinsic server objects
/// </param>
private delegate void EnqueueDelegate(HttpContext context);
/// <summary>
/// Adds the method to the queue.
/// </summary>
/// <param name="context">
/// the <see cref="T:System.Web.HttpContext">HttpContext</see> object that
/// provides references to the intrinsic server objects
/// </param>
private void Enqueue(HttpContext context)
{
imageOperations.Enqueue(() => ProcessImage(context));
}
謝謝你,是的,我一定會改變字段名稱。 :)你在'OnEndAsync'上找到的東西很多,我從MSDN的示例中得到了4個線程位,我不確定它對我的過程是有利的還是有害的。話雖如此,將過程簡化爲一個線程似乎已使我的測試頁面加速了大約20%。保持一個還是可以的,或者你能否提出一種更多線程可以以更有利的方式使用的方法? – 2013-03-20 19:11:02
謝謝你......不幸的是,你的編輯似乎已經打破了一些東西。這些圖像肯定會得到處理並保存到文件系統,但現在將以原始未處理的形式返回給瀏覽器。 – 2013-03-20 20:17:10
是的,這是有道理的。回到繪圖板,如果我想要更多的速度:/ – 2013-03-20 20:46:53