shah.nilang Ответов: 1

Как реализовать backgroundworker или threading in ASP.NET(C#) 4.0 веб-приложение для экспорта большого объема данных в excel?


Я хочу экспортировать некоторые сложные данные в лист excel, который занимает больше времени и блокирует приложение, так что пользователь не может двигаться дальше, пока эта задача не будет завершена, поэтому я использовал backgroundworker для этого, но все же он блокирует приложение, и пользователь должен ждать, пока функция экспорта не будет завершена. Есть ли какие-либо другие подходы, доступные для этого, или что я должен изменить в своем коде, чтобы реализовать его? для экспорта данных в excel я использую библиотеку ClosedXML и мое приложение работает на .net 4.0

Что я уже пробовал:

<%@ Page Title="" Language="C#" MasterPageFile="~/export_module.master"
AutoEventWireup="true" CodeFile="GenerateReport.aspx.cs"
Inherits="" Async="true" %>


public readonly BackgroundWorker worker = new BackgroundWorker();

protected void Page_Load(object sender, EventArgs e)
{
 if (!Page.IsPostBack)
    {
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;
        worker.DoWork += new DoWorkEventHandler(DoWork);
        //worker.ProgressChanged += new ProgressChangedEventHandler(WorkerProgressChanged);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
    }
}

protected void btn_Export_Click(object sender, EventArgs e)
  {        
    if (!worker.IsBusy){
      worker.RunWorkerAsync("ExportReport");
    }
  }     


 private void DoWork(object sender, DoWorkEventArgs e)
  {
    exportToExcel();
  }

  private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  { 
  }

 public void ExportReportWithHeaderClosedXML(string reportName, string fileName,  DataTable dataTable)
{
    int usedCells = dataTable.Columns.Count;
    string ReportDate = string.Empty;
    string attachment = "inline;filename=" + fileName + ".xlsx";
    using (XLWorkbook wb = new XLWorkbook())
    {

        //Add method of ClosedXML class library only accepts worksheet name of 31 characters.

        IXLWorksheet worksheet = wb.Worksheet(1);           

        //Insert Report Data
        worksheet.Cell(4, 1).InsertTable(dataTable);
        HttpContext.Current.Response.Clear();

        HttpContext.Current.Response.ClearContent();
        HttpContext.Current.Response.ClearHeaders();
        HttpContext.Current.Response.Buffer = true;

        HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
        HttpContext.Current.Response.AddHeader("Content-Disposition", "inline;filename=" + fileName + ".xlsx");
        using (MemoryStream MyMemoryStream = new MemoryStream())
        {
            wb.SaveAs(MyMemoryStream);
            MyMemoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
            HttpContext.Current.Response.End();
        }
    }
}

1 Ответов

Рейтинг:
4

Richard Deeming

Нет никакого смысла в использовании BackgroundWorker для этого. Это не будет иметь никакого значения - браузер будет застрять в ожидании ответа от сервера, пока сервер не отправит ответ. Передача кода, генерирующего ответ, в фоновый поток только увеличит нагрузку на сервер, не влияя на то, что происходит на клиенте.

Если вы хотите, чтобы пользователь мог продолжать взаимодействовать с вашим сайтом во время создания файла Excel, вам нужно будет внести некоторые изменения:

  • Генерация Excel должна происходить в отдельном обработчике - предпочтительно в "универсальном обработчике" (.ashx файл).
  • Обработчик, который генерирует файл Excel, должен отключить состояние сеанса. Если вы этого не сделаете, другие запросы из того же сеанса будут заблокированы до тех пор, пока обработчик не завершит работу.
  • Замените его <asp:Button> который в настоящее время запускает загрузку с помощью <asp:HyperLink> указывая на обработчик Excel.
  • Набор target="_blank" на HyperLink так что ссылка откроется в новой вкладке. Если вы этого не сделаете, браузер заморозит текущую страницу до завершения навигации.

Это ни в коем случае не идеально - пользователь увидит пустую вкладку во время загрузки и должен будет переключиться обратно на предыдущую вкладку, чтобы продолжить взаимодействие с вашим сайтом. Если они закроют пустую вкладку, Загрузка будет отменена.

Лучшим вариантом было бы потренироваться почему? ваш экспорт занимает так много времени, и найдите способ ускорить его. Это потребует от вас профилирования кода, чтобы найти узкое место.


shah.nilang

Можете ли вы привести пример этого, поскольку я не могу экспортировать файл из обработчика?

Richard Deeming

Что-то вроде этого:

<%@ WebHandler Language="C#" %>

using System;
using System.Data;
using System.Web;
using ClosedXML.Excel;
// TODO: Add other required namespaces here...

public class ExcelReportHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }
    
    public void ProcessRequest (HttpContext context)
    {
        DataTable reportData = LoadReportData(context);
        string fileName = "...Your filename here...";
        string reportName = "...Your report name here...";
        
        using (XLWorkbook wb = CreateReport(reportName, reportData))
        {
            context.Response.ContentType = "application/vnd.ms-excel";
            context.Response.AddHeader("Content-Disposition", "inline;filename=" + fileName + ".xlsx");
            
            using (MemoryStream ms = new MemoryStream())
            {
                wb.SaveAs(ms);
                ms.Seek(0L, SeekOrigin.Begin);
                ms.WriteTo(context.Response.OutputStream);
            }
        }
    }
    
    private static XLWorkbook CreateReport(string reportName, DataTable dataTable)
    {
        XLWorkbook wb = new XLWorkbook();
        IXLWorksheet worksheet = wb.Worksheet(1);
        worksheet.Cell(4, 1).InsertTable(dataTable);
        return wb;
    }
    
    private static DataTable LoadReportData(HttpContext context)
    {
        ...Load the report data here...
    }
}

shah.nilang

Процесс был успешно завершен, но файл не загружается