摘要
在ASP中使用异步页面时,如何避免TimeoutException
或在TimeoutException
之后继续呈现页面?NET WebForms?
如果不能使用PageAsyncTask
取消令牌来避免Timeout Exception
,那么PageAsyncTask
取消令牌有什么作用?
详情
我正在调用一个异步端点来获取要在WebForms页面中显示的结果。大多数情况下,这工作得很好,但是,当端点花费太长时间返回结果时,整个页面将显示黄色屏幕
[TimeoutException: An asynchronous operation exceeded the page timeout.
我不想简单地任意增加Page.AsyncTimeout
。相反,我想处理超时,并处理页面的其余部分,为页面的部分显示我自己的消息,这取决于超时的异步任务。
对于构造函数
public PageAsyncTask (Func<System.Threading.CancellationToken,System.Threading.Tasks.Task> handler);
Microsoft文档指出:
ASP.NET将根据网页的@ Page指令中设置的AsyncTimeout属性,向传递给TaskEventHandler委托的CancellationToken对象发送取消信号。当达到AsyncTimeout值时,将发出CancellationToken对象的信号。CancellationToken参数必须传递给TaskEventHandler类的实现所调用的任何异步API。
但是,即使这样做,我仍然得到页面级别TimeoutException
。
构造函数的另一个重载提供超时处理程序
public PageAsyncTask (System.Web.BeginEventHandler beginHandler, System.Web.EndEventHandler endHandler, System.Web.EndEventHandler timeoutHandler, object state);
然而,似乎没有办法将Task
与timeoutHandler
一起使用。这似乎意味着处理cancellationToken应该足够了,但显然不是。
此外,TimeoutException
似乎是在一个不可能以一种有用的(对我来说)方式实际捕获它的点上抛出的--Page.Error
事件似乎太晚了,无法恢复页面的呈现。
这似乎引出了另一个问题,即使用public PageAsyncTask (Func<System.Threading.CancellationToken,System.Threading.Tasks.Task> handler);
而不是public PageAsyncTask (Func<System.Threading.Tasks.Task> handler);
的意义是什么?
示例代码
- 默认.aspx*
<%@ Page Async="true" AsyncTimeout="5" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Foo.Default" %>
<%-- ... --%>
<form runat="server">
<asp:Button ID="btnGetInfo" runat="server" Text="Get Info" onclick="btnGetInfo_Click" UseSubmitBehavior="false" />
<asp:TextBox ID="txtInfo" runat="server" />
<asp:Label ID="lblError" runat="server" />
<%-- ... --%>
</form>
- Default. aspx。cs*
namespace Foo
{
public partial class Default : System.Web.UI.Page
{
private readonly DummyService _dummyService = new DummyService();
protected void btnGetInfo_Click(object sender, EventArgs e)
{
txtInfo.Text = "";
lblError.Text = "";
async Task btnGetInfoClickAsync(CancellationToken cancellationToken)
{
//also tried:
//cancellationToken.Register(() => lblError.Text = "Timeout, data not retrieved", useSynchronizationContext: true);
try
{
string info = await _dummyService.GetInfoAsync(cancellationToken);
txtInfo.Text = info;
}
catch (TaskCanceledException)
{
lblError.Text = "Timeout, data not retrieved";
}
}
RegisterAsyncTask(new PageAsyncTask(btnGetInfoClickAsync));
}
}
}
- DummyService。cs*
namespace Foo
{
public class DummyService
{
public async Task<string> GetInfoAsync(CancellationToken cancellationToken)
{
await Task.Delay(6000, cancellationToken).ConfigureAwait(false);
return Path.GetRandomFileName();
}
}
}
- 网站配置 *
<configuration>
<!-- ... -->
<system.web>
<httpRuntime targetFramework="4.8">
<compilation debug="true" targetFramework="4.8">
<!-- ... -->
</system.web>
<!-- ... -->
</configuration>
1条答案
按热度按时间fykwrbwg1#
避免
TimeoutException
并允许继续处理页面的简单方法是:PageAsyncTask (Func<Task> handler)
构造函数而不是PageAsyncTask (Func<CancellationToken, Task> handler)
构造函数Page.AsyncTimeout
之前到期。这假设你调用的async API接受并正确响应
CancellationToken
。例如 * 默认。aspx.cs*
(我仍然不理解
PageAsyncTask (Func<CancellationToken, Task> handler);
构造函数的实用程序)