Ожидание выполнения длительного процесса в ASP.NET

Допустим, у нас есть страница Default.aspx, на которой пользователь вводит имя клиента и номер накладной, после чего происходит проверка этого номера. Поскольку проверка может занимать длительное время, то необходимо обеспечить пользователя информацией о ходе выполнения процесса (идет или уже прошел). Наипростейший способ приведен ниже.

Default

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;

public
partial class _Default : System.Web.UI.Page
{

    protected
Guid _id;

    protected
void Page_Load(object sender, EventArgs e)
    {
        if (
Page.IsPostBack)
        {
            
_id = Guid.NewGuid();

            
ThreadStart ts = new ThreadStart(Check);
            
Thread th = new Thread(ts);
            
th.Start();

            
Response.Redirect("Invoice.aspx?ID=" + _id.ToString());
        }
    }

    protected
void Check()
    {
       
string res = InvoiceProcessor.CheckInvoice(txtName.Text, txtNumber.Text);
       
CheckedInvoices.Add(_id, res);
    }

}

Суть в том, что создается уникальный идентификатор. По которому результат будет получен из хэш-таблицы результатов. Пример класса таблицы CheckedInvoices и класса-заглушки, который в нормальном приложении выполняет проверку InvoiceProcessor, приведены ниже.

CheckedInvoices

using System;
using System.Collections;

public static class
CheckedInvoices
{
    private static
Hashtable _invoices = new Hashtable();

    public static
string GetResult(Guid id)
    {
        if (
_invoices.Contains(id))
        {
            return
Convert.ToString(_invoices[id]);
        }
        else
        {
            return
"";
        }
    }

    public static
void Add(Guid id, string value)
    {
       
_invoices[id] = value;
    }

    public static
void Remove(Guid id)
    {
       
_invoices.Remove(id);
    }
}

InvoiceProcessor

using System;
using System.Threading;

public static class
InvoiceProcessor
{
    public static
string CheckInvoice(string customerName, string invoiceID)
    {
       
Thread.Sleep(10000);
        if (
invoiceID == "qwerty")
        {
            return
"Текущий статус: передано в службу доставкиnОжидаемое время доставки: черт его знает";
        }
        else if(
invoiceID == "asdfgh")
        {
            return
"Текущий статус: доставленоnОжидаемое время доставки: дык уже";
        }
        else
        {
            return
"Нет информации по данной накладной";
        }
    }
}

Страница, на которую выполняется переадресация, должна лишь проверять готовность результата.

Invoice

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public
partial class Invoice : System.Web.UI.Page
{
    protected
void Page_Load(object sender, EventArgs e)
    {
        if (
Request.Params["ID"] != null)
        {
            
Guid id = new Guid(Request.Params["ID"]);

            if (
CheckedInvoices.GetResult(id).Length == 0)
            {
               
phInvoice.Controls.Add(new LiteralControl("Пожалуйста, подождите..."));
               
Response.AddHeader("Refresh", "5");
            }
            else
            {
               
phInvoice.Controls.Add(new LiteralControl(CheckedInvoices.GetResult(id)));
               
CheckedInvoices.Remove(id);
            }
        }
        else
        {
            
phInvoice.Controls.Add(new LiteralControl("Не указан идентификатор накладной."));
        }
    }
}

Схема очень проста - на странице Default.aspx происходит постбэк, в этот момент создается новый уникальный идентификатор, который передается методу, выполняемумо в отдельном процессе. После этого происходит переадресация на страницу Invoice.aspx, где происходит проверка по идентификутору (переданому в GET запросе) в таблице CheckedInvoices, нет ли там данных. Если данных нет, то посылается заголовок, сообщающий браузеру о необходимости сделать Refresh, если же результат появился, то пользователю выводится результат, а ключ удаляеся из хэш-таблицы, поскольку больше не нужен.

Автор: нет данных