c# - 在 ASP.NET MVC 中检测异步客户端断开连接

标签 c# asp.net-mvc asynchronous

给定一个异步 Controller :

public class MyController : AsyncController 
{
    [NoAsyncTimeout]
    public void MyActionAsync() { ... }

    public void MyActionCompleted() { ... }
}

假设 MyActionAsync 启动一个需要几分钟的过程。如果用户现在转到 MyAction 操作,浏览器将等待连接打开。如果用户关闭浏览器,则连接关闭。是否可以检测到服务器上发生这种情况的时间(最好是在 Controller 内部)?如果是这样,如何?我已经尝试覆盖 OnException 但在这种情况下永远不会触发。

注意:我非常感谢下面提供的有用答案,但这个问题的关键方面是我正在使用 AsyncController。这意味着 HTTP 请求仍处于打开状态(它们像 COMET 或 BOSH 一样长期存在)这意味着它是实时套接字连接。当此实时连接终止(即“连接由对等方重置”,TCP RST 数据包)时,为什么不能通知服务器?

最佳答案

我知道这个问题很老,但在我搜索相同答案时经常出现。 以下详细信息仅适用于 .Net 4.5

HttpContext.Response.ClientDisconnectedToken是你想要的。那会给你一个 CancellationToken你可以传递给你的异步/等待调用。

public async Task<ActionResult> Index()
{
    //The Connected Client 'manages' this token. 
    //HttpContext.Response.ClientDisconnectedToken.IsCancellationRequested will be set to true if the client disconnects
    try
    {
        using (var client = new System.Net.Http.HttpClient())
        {
            var url = "http://google.com";
            var html = await client.GetAsync(url,  HttpContext.Response.ClientDisconnectedToken);
        }
    }
    catch (TaskCanceledException e)
    {
        //The Client has gone
        //you can handle this and the request will keep on being processed, but no one is there to see the resonse
    }
    return View();
}

您可以通过在函数开头放置断点然后关闭浏览器窗口来测试上面的代码段。


还有另一个片段,与您的问题没有直接关系,但同样有用...

您还可以使用 AsyncTimeout 对操作可以执行的时间量施加硬性限制。属性。要使用此功能,请添加类型为 CancellationToken 的附加参数。如果执行时间过长,此 token 将允许 ASP.Net 使请求超时。

[AsyncTimeout(500)] //500ms
public async Task<ActionResult> Index(CancellationToken cancel)
{
    //ASP.Net manages the cancel token.
    //cancel.IsCancellationRequested will be set to true after 500ms
    try
    {
        using (var client = new System.Net.Http.HttpClient())
        {
            var url = "http://google.com";
            var html = await client.GetAsync(url, cancel);
        }
    }
    catch (TaskCanceledException e)
    {
        //ASP.Net has killed the request
        //Yellow Screen Of Death with System.TimeoutException
        //the return View() below wont render
    }
    return View();
}

您可以通过在函数的开头放置一个断点(从而使请求在遇到断点时花费超过 500 毫秒)然后让它运行来测试它。

关于c# - 在 ASP.NET MVC 中检测异步客户端断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4772597/

相关文章:

asp.net-mvc - 如何使用 Html.DropDownListFor(...) 格式化日期时间

asp.net-mvc - 将 PagedList 与 ViewModel 结合使用

javascript - Chrome 扩展 : make chrome. tabs.query() 同步

c# - 扩展 Entity Framework 的工作单元

c# - 如何从 MVC/Razor 页面将参数传递到顶级服务器端 blazor 组件?

c# - 重构基于多个参数进行计算的类的最佳设计模式

c# - UWP 将 MenuFlyout(Item) 动态添加到现有的 menuflyout

c# - ASP.NET MVC 如何动态创建 Controller 和 View ?

python - 如何将基于回调的异步函数转换为异步生成器

javascript - 为 Mongodb 创建多个动态对象 NodeJs 查询