取消当前的同步请求处理

时间:2018-07-12 08:22:04

标签: c# .net entity-framework webforms task-parallel-library

我正在尝试取消用户当前的请求。 Web Forms Web App具有导出到excel功能。如果生成Excel报告的时间很长,则用户可以取消该请求。

单击取消按钮后,服务器应停止处理以节省宝贵的带宽。

我发现了以下两种解决方案。

第一个解决方案:

直接跳转到Application_EndRequest事件,以防止执行更多代码。

    protected void btnCancel_Click(object sender, EventArgs e)
    {

        if (Response.IsClientConnected)
        {

            HttpContext.Current.ApplicationInstance.CompleteRequest();

        }


    }

第二个解决方案:(使用任务并行库-TPL)

   CancellationTokenSource tokenSource = new CancellationTokenSource();


    protected void Page_Load(object sender, EventArgs e)
    {

    }


    protected void btnExportExcel_Click(object sender, EventArgs e)
    {
        CancellationToken cToken = tokenSource.Token;

        Task.Factory.StartNew(() =>
        {
                // do some heavy work here

                GenerateReport(sender, cToken);

                if (cToken.IsCancellationRequested)
                {

                // another thread decided to cancel
                  return;

                }

        }, cToken);

        // to register a delegate for a callback when a
        // cancellation request is made

        cToken.Register(() => cancelNotification());

    }

    private void GenerateReport(object sender, CancellationToken ct)
    {

    var students = _context.Students.ToList();

    var courses = _context.Courses.ToList();

    var teachers = _context.Teachers.ToList();

    // Todo: Use above data to Generate Excel Report

    // Just to Simulate Export to excel

        Thread.Sleep(7000);

    }


    protected void btnCancel_Click(object sender, EventArgs e)
    {

            tokenSource.Cancel();

    }


    private static void cancelNotification()
    {
        // Why never called ?

    }

在第二个解决方案中,我使用了Task Parallel Library (TPL)并在注销时使用了CancellationToken注册了一个回调方法。我有几个问题:

  1. 但是当我单击取消按钮时,从未调用过回调方法,我知道为什么吗?

  2. 我可以使用Entity framework取消所有3条.ToList()语句,然后再命中数据库以获取数据。

  3. 我也可以知道与TPL一起使用是最好的选择吗?

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我认为您必须在启动Task之前注册回调函数。您的代码必须看起来像这样。

在Page_Load方法中,您必须在用户会话中保存CancellationTokenSource。

public partial class Contact : Page
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();


    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.Session["Cart"] != null)
        {
            tokenSource = HttpContext.Current.Session["Cart"] as CancellationTokenSource;
        }
        else
        {
            HttpContext.Current.Session.Add("Cart", new CancellationTokenSource());
            tokenSource = HttpContext.Current.Session["Cart"] as CancellationTokenSource;
        }
    }


    protected void btnExportExcel_Click(object sender, EventArgs e)
    {
        CancellationToken cToken = tokenSource.Token;
        cToken.Register(() => cancelNotification());

        Task.Factory.StartNew(() =>
        {
        // do some heavy work here

        GenerateReport(sender, cToken);

            if (cToken.IsCancellationRequested)
            {

            // another thread decided to cancel
            return;

            }

        }, cToken);
    }

    private void GenerateReport(object sender, CancellationToken ct)
    {

        var students = _context.Students.ToList();

        var courses = _context.Courses.ToList();

        var teachers = _context.Teachers.ToList();

        // Todo: Use above data to Generate Excel Report

        // Just to Simulate Export to excel

        Thread.Sleep(7000);

    }


    protected void btnCancel_Click(object sender, EventArgs e)
    {

        tokenSource.Cancel();

    }


    private static void cancelNotification()
    {
        // Why never called ?

    }
}

您的第二个问题。

您可以异步加载列表。使用方法ToListAsync(),您可以在其中输入canalactiontoken。

Microsoft Dokumentation

希望对您有帮助吗?