我正在尝试取消用户发出的当前请求。Web窗体Web应用程序具有导出到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 ?
}
在第二个解决方案中,我使用了任务并行库(TPL(,并使用CancellationToken
注册了取消时的回调方法。我有几个问题:
但当我单击取消按钮时,回调方法从未被调用,我知道为什么吗?
使用
Entity framework
,我可以在它到达数据库获取数据之前取消所有3个.ToList()
语句。我还可以知道使用
TPL
是最好的选择吗?
如有任何帮助,我们将不胜感激。
我认为在启动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()
,您可以在其中提供您的Canaactiontoken。
Microsoft文档
我希望这对你有帮助?