I want to export some complex data into excel sheet which takes more time and block application so that user cannot proceed further until this task has completed so i have used backgroundworker for that but still it block application and user has to wait until export functionality will completed. Is there any other approaches available for that or what should i change in my code to implement it? to export data into excel i am using ClosedXML Library and my application is on .net 4.0
What I have tried:
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();
}
}
}
解决方案There's no point in using a BackgroundWorker for this. It won't make any difference - the browser will be stuck waiting for the response from the server until the server sends the response. Pushing the code that generates the response onto a background thread will just put more strain on the server, without affecting what happens on the client.
If you want the user to be able to continue interacting with your site whilst the Excel file is being generated, you're going to need to make some changes:
The Excel generation needs to happen in a separate handler - preferably a "generic handler" (.ashx file).
The handler which generates the Excel file needs to disable session state. If you don't, other requests from the same session will be blocked until the handler finishes.
Replace the which currently triggers the download with a pointing to the Excel handler.
Set target="_blank" on the HyperLink so that the link opens in a new tab. If you don't, the browser will freeze the current page until the navigation is complete.
This is by no means perfect - the user will see a blank tab whilst the download is being generated, and will have to switch back to the previous tab to continue interacting with your site. If they close the blank tab, the download will be cancelled.
A better option would be to work out why your export is taking so long, and find a way to speed it up. This would require you to profile your code to find the bottleneck.