TransWikia.com

¿Cómo cancelar tarea asíncrona en Asp.Net Mvc?

Stack Overflow en español Asked by Efrain Mejias C on August 27, 2021

Escribi este codigo para cancelar una tarea asincrona pero no la esta cancelando:

    private CancellationTokenSource _cts1 = new CancellationTokenSource();
        private CancellationToken _ct1;
        private CancellationTokenSource _cts2 = new CancellationTokenSource();
        private CancellationToken _ct2;
        private CancellationTokenSource _cts3 = new CancellationTokenSource();
        private CancellationToken _ct3;
        private CancellationTokenSource _cts4 = new CancellationTokenSource();
        private CancellationToken _ct4;

   public ActionResult Report(ReportFilterModel filterModel, int report)
        {
            if (Session["GeneratingReport"] == null || !(bool)Session["GeneratingReport"])
            {
                _cts1 = new CancellationTokenSource();
                _ct1 = _cts1.Token;
                _cts2 = new CancellationTokenSource();
                _ct2 = _cts2.Token;
                _cts3 = new CancellationTokenSource();
                _ct3 = _cts3.Token;
                _cts4 = new CancellationTokenSource();
                _ct4 = _cts4.Token;

                Session["GeneratingReport"] = true; //Se registra en sesión
                string basePath = ConfigurationManager.AppSettings["BaseFilePath"] + "/ReportesExcel/";
                string fileName = null;
                try {
                    switch (report)
                    {
                        case 1:
                            fileName = "report-users" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                            Task.Factory.StartNew(() => ExportReport(filterModel, basePath + fileName,_ct1),_ct1);
                            break;
                        case 2:
                            fileName = "report-plays" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                           Task T = Task.Factory.StartNew(() => ExportReportPlays(filterModel, basePath + fileName,_ct2), _ct2);
                            break;
                        case 3:
                            fileName = "reporte-compras" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                            Task.Factory.StartNew(() => ExportReportPurchases(filterModel, basePath + fileName,_ct3), _ct3);
                            break;
                        case 4:
                            fileName = "reporte-ventas-distribuidor" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                            Task.Factory.StartNew(() => ExportReportDistributorPurchases(filterModel, basePath + fileName,_ct4), _ct4);
                            break;
                    }
                    Session["ReportPath"] = basePath + fileName;
                }
                catch(Exception ex) 
                { 
                    string error =  ex.ToString();
                }
                
            }
            return Content("Generando Reporte");
        }

Aqui un ejemplo del metodo que invoco:

public async Task ExportReport(ReportFilterModel filterModel, string path, CancellationToken _ct)
    {
        try
        {

            while (!_ct.IsCancellationRequested)
            {
                using (var taskDb = new CmsLiteData()) //Se define contexto de ejecución de la conexión para la tarea Asyncrona, forzando la llamada de dispose cuando finalice
                {
                    this.GenerateExcel(filterModel, "Informe compra y recompra (cantidad de usuarios únicos)", true, path, taskDb);
                }
            }
        }
        catch (Exception ex)
        {
            _cts1.Cancel();
            CmsHelper.SetLog(ex.ToString(), 1, "PurchaseReportController", "ExportReport", "TareaAsincrona", "N/A", "N/A");
        }
    }

Aqui el metodo desde donde trato de cancela no devuelve error pero no cancela la tarea:

  public ActionResult CancelTaskGenerateReport (int idReport)
        {
            string nameReport = string.Empty;
            switch (idReport)
            {
                case 1:
                    nameReport = "Reporte de compra/recompra";
                    _cts1.Cancel();
                    break;
                case 2:
                    nameReport = "Reporte de reproducciones";
                    _cts2.Cancel();
                    break;
                case 3:
                     nameReport = "Reporte de compra";
                    _cts3.Cancel();
                    break;
                case 4:
                    nameReport = "Reporte de ventas";
                    _cts4.Cancel();
                    break;

            }
            return Content("Generacion de Reporte Cancelada");
        }

One Answer

Te faltaria crear el token de cancelacion y pasarlo como parametro a tu metodo y cuando creas la tarea tambien se pasa como parametro. En el caso de querer cancelar una sola tarea cuando varias se ejecutan, deberias crear la cantidad de token necesarios para cada metodo.

Tenes que crear dos variables y luego un boton donde canceles la tarea.

CancellationTokenSource Cts;
CancellationToken ct;
CancellationTokenSource Cts2;
CancellationToken ct2;

En mi caso como prueba uso un comboBox para seleccionar que tarea cancelar.

    private void button2_Click(object sender, EventArgs e)
    {
        if (comboBox1.SelectedIndex == 0)
        {
            Cts.Cancel();
        }
        else if (comboBox1.SelectedIndex == 1)
        {
            Cts2.Cancel(); 
        }
    }
  
    public ActionResult Report(ReportFilterModel filterModel, int report)
    {            
          Cts = new CancellationTokenSource();
          Cts2 = new CancellationTokenSource();
          ct = Cts.Token;
          ct1 = Cts2.Token;

        if (Session["GeneratingReport"] == null || !(bool)Session["GeneratingReport"])
        {
            Session["GeneratingReport"] = true; //Se registra en sesión
            string basePath = ConfigurationManager.AppSettings["BaseFilePath"] + "/ReportesExcel/";
            string fileName = null;
            try {
                switch (report)
                {
                    case 1:
                        fileName = "report-users" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                        Task.Factory.StartNew(() => ExportReport(filterModel, basePath + fileName, ct), ct);
                        break;
                    case 2:
                        fileName = "report-plays" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                       Task T = Task.Factory.StartNew(() => ExportReportPlays(filterModel, basePath + fileName , ct2), ct2);
                        break;
                    case 3:
                        fileName = "reporte-compras" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                        Task.Factory.StartNew(() => ExportReportPurchases(filterModel, basePath + fileName, ct), ct);
                        break;
                    case 4:
                        fileName = "reporte-ventas-distribuidor" + "-" + DateTime.Now.ToString("yyyyMMddhmmss") + ".xlsx";
                        Task.Factory.StartNew(() => ExportReportDistributorPurchases(filterModel, basePath + fileName, ct), ct);
                        break;
                }
                Session["ReportPath"] = basePath + fileName;
            }
            catch(Exception ex) 
            { 
                string error =  ex.ToString();
            }
            
        }
        return Content("Generando Reporte");
    }

Los metodos que invoco tienen esta forma, aqui el ejemplo:

    public async Task ExportReport(ReportFilterModel filterModel, string path, CancellationToken ct)
    {
        try
        {
          while(!ct.IsCancellationRequested)
          {
            using (var taskDb = new CmsLiteData()) //Se define contexto de ejecución de la conexión para la tarea Asyncrona, forzando la llamada de dispose cuando finalice
            {
                this.GenerateExcel(filterModel, "Informe compra y recompra (cantidad de usuarios únicos)", true, path, taskDb);
            }
          }
        }
        catch (Exception ex)
        {
            CmsHelper.SetLog(ex.ToString(), 1, "PurchaseReportController", "ExportReport", "TareaAsincrona", "N/A", "N/A");
        }
    }

Answered by Ramiro Barone on August 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP