65.9K
CodeProject 正在变化。 阅读更多。
Home

QBWI - 你的后台进程拯救者

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (91投票s)

2016 年 7 月 29 日

CPOL
viewsIcon

18854

如何在 IIS 环境中利用 QueueBackgroundWorkItem(QBWI) 为 Web 应用程序运行后台进程。

引言

在 Web 环境(特别是 ASP.NET)中,有时需要由于当前进程的延续或作为独立的长时间运行进程而在后台运行进程。 如果 Web 应用程序恰好托管在 IIS 中,由于 应用程序池[^] 的回收,IIS 可能会中断后台进程。 QueueBackgroundworkItem(QBWI)[^] 允许您确保在刷新应用程序池之前完成后台进程。 以下是如何使用它。

注意:QBWI 支持 .NET 4.5.2 及更高版本。

Using the Code

从以下示例代码中,假设 GetPayLoad 方法在几秒钟内返回响应,但由于各种原因,可能需要超过期望的响应时间间隔,在本例中为 5 秒。 假设我们也有以下类用于演示。

public class Request
{
    public int Id { get; set; }
    public string Content { get; set; }
    // Other properties goes here
}

public class Response
{
    public int Id { get; set; }
    public string Message { get; set; }
    public string PayLoad { get; set; }
    // Other properties goes here
}

using System.Web.Hosting;
// Other namespaces ...
        
public class RequestProcessor
{
    public Response ProcessRequest(Request request)
    {
        Response response = new Response();
        try
        {
            Task<Response> task = new TaskFactory().StartNew(
              () =>
              {
                  return GetPayload(request); // Suppose you have this method in the app
              });

            task.Wait(5000); // Wait 5 seconds
            if (!task.IsFaulted)
            {
                if (!task.IsCompleted)
                {
                    response.Message = "Error";
                    // Ensure the backrground task will be completed before IIS recycles the request
                    HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
                    {
                        task.ContinueWith((r) =>
                        {
                            response = r.Result;
                            // Log the background task response
                        });
                    });
                }
                else
                {
                    response = task.Result;
                    response.Message = "Success";
                }
             }
             else
             {
                 response.Message = "Error";
             }
        }
        catch (Exception exception)
        {
            // Log exception
            response.Message = "Error";
        }
        return response;
    }

    public Response GetPayload(Request request)
    {
        Response response = new Response();
        /* Save the data to DB and return the Payload
           Do other things with the request
           ...
           ...
           ...
        */
        response.PayLoad = "Some content";
        return response;
    }
}

您还可以利用 CancellationToken 来检查 IIS 或 IIS Express 是否在回收自身之前被强制刷新或关闭,例如:

if(cancellationToken.IsCancellationRequested)
{
   // Log something like IIS cancelled the operation 
}

历史

  • 2016 年 7 月 29 日:首次版本 1.0
© . All rights reserved.