Method cancellation by user input or no response
The website I work on allows users to generate reports between two dates selected by the user. The problem I'm running into is that if a user accidentally requests a report between a huge difference between dates, i.e. one year, the server is under a lot of pressure and can sometimes crash for all users. What I should do is have some kind of progress bar showing the user how long it will take from the report, and a cancel button or button to check if they are all there. I have searched for using an assignment undo token but not sure if this is what I want. also thought of a globally linked list with random numbers associated with true false as a user can open many reports at the same time. I've included some of the relevant code below.I would appreciate any help or point in the right direction, thanks
// java script which is passed from and dated and calls genonereport method
window.open('genonereport?idd=' + idd + '&fromm=' +
fromm + '&too=' + too + '&filetype=' + outputValue ,
'_blank');
// genonereport passes the values ββto the class below, which contains the corresponding method --- report.render, which is the method I want to cancel if the user cancels the report or leaves
public byte[] genReportBytes(int id, string fromm, string too, string filetype)
{
reportDetails repD = new reportDetails();
repD = getOneReport(id);
LocalReport report = new LocalReport();
if (fromm != null)
repD.ParametersCommandLine = "@startdate=" + fromm;
if (too != null)
repD.ParametersCommandLine += " @enddate=" + too;
string RDLCPath = ConfigurationManager.AppSettings["RDLCPath"];
string ReportOutputPath = ConfigurationManager.AppSettings["ReportOutputPath"];
string RDLCName = repD.RDLCName;
RDLCPath += @"\" + RDLCName;
report.ReportPath = RDLCPath;
string sqlGet = repD.SQLOfReport;
report.DataSources.Add(new ReportDataSource(repD.DatasetName, getReportData(sqlGet, repD.ParametersCommandLine)));
// export to byte array
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
string deviceInf = "";
byte[] bytes = new byte[64];
byte[] empty = null;
string extension;
bool Completed;
if (filetype == "pdf")
{
deviceInf = "<DeviceInfo><PageHeight>8.5in</PageHeight><PageWidth>11in</PageWidth><MarginLeft>0in</MarginLeft><MarginRight>0in</MarginRight></DeviceInfo>";
//fileName = ReportOutputPath + @"\" + repD.NameOfOutputPDF + ".PDF";
//Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(5000), () =>
//{
bytes = report.Render("pdf", deviceInf, out mimeType, out encoding, out filenameExtension,
out streamids, out warnings);
//});
}
else
{
//fileName = ReportOutputPath + @"\" + repD.NameOfOutputPDF + ".XLS";
//Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(5000), () =>
//{
bytes = report.Render(
"Excel");
//});
}
//if (Completed == true)
//{
return bytes;
//}
//else
//return empty;
}
// I got this far, but it only gets canceled after a certain amount of time, which is not good for me.
public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
Sorry for the long term question, thanks again
source to share
You will need at least three web endpoints:
- one to generate a report and return results
- one that your Javascript can periodically request to check progress.
- which your browser may request to cancel the task.
You will need to store the descriptor of each task in a dictionary with some kind of ID, so you can pass the ID to requests 2 and 3.
This article gives you an example on how to do this.
It's not easy, so limiting the report size that users can generate may be preferable.
source to share