【问题标题】:Response.Redirect issue with Asp.net asyncAsp.net 异步的 Response.Redirect 问题
【发布时间】:2013-12-07 12:11:55
【问题描述】:

我是 asp.net 4.5 异步的新手,在异步方法中调用 response.redirect 时遇到以下问题。问题是响应只是“挂起”有没有其他人在尝试异步重定向时遇到过类似的问题?此代码适用于全新项目,但不适用于我们现有代码中的新页面。我确保从我们的 web.config 中删除所有可能的内容并删除我们的母版页。撞砖墙……有什么想法吗?谢谢!

    protected void Page_Load(object sender, EventArgs e)
    {
        RegisterAsyncTask(new PageAsyncTask(PageLoadAsync));
    }

    private async Task PageLoadAsync()
    {
        var data = await GetData();

        if (data == HttpStatusCode.OK)
            Response.Redirect("http://www.google.com");
    }

    private async Task<HttpStatusCode> GetData()
    {
        using (var client = new HttpClient())
        {
            var response = await client.GetAsync("https://www.google.com");
            return response.StatusCode;
        }
    }

【问题讨论】:

  • 我认为你不能在异步线程上执行Redirect
  • 我不明白你为什么需要异步,你仍然需要等待 HttpClient 在完成加载/渲染页面之前响应。而且您不会同时做多件事。顺便说一句:如果你有互联网连接,谷歌将永远工作;)
  • 他需要异步,因为他正在执行 I/O 密集型任务(向远程资源发送 HTTP 请求)。想象一下,这个资源需要很长时间才能响应。在此期间,您将危及您的 ASP.NET 工作线程。现在假设这个端点同时被 200 个用户访问 => 你的站点将会死掉,因为没有任何工作线程可用于服务请求。这就是为什么在这种情况下使用异步非常重要。
  • @DarinDimitrov,工作线程将如何获得响应?还是服务器会将更新(块)推送到 HTML5 websockets 之类的客户端?我还在困惑how RegisterAsyncTask works?
  • client.GetAsync 方法使用 I/O 完成端口。你可以在这里阅读更多关于它们的信息:msdn.microsoft.com/en-us/magazine/cc163463.aspx。服务器到服务器的通信中没有块或 HTML5 WebSockets。

标签: c# asp.net async-await response.redirect


【解决方案1】:

此代码适用于全新项目,但不适用于我们现有代码中的新页面。

我假设您现有的网站已经升级到 .NET 4.5。

首先要检查的是httpRuntime.targetFramework 设置为4.5。这是在您升级时默认设置的。

从 cmets 编辑:

要检查的另一件事(以防万一)是 Page.Async 设置为 true

在这种情况下,解决方案是调用Response.Redirect("http://www.google.com", false),它为endResponse 参数显式传递falsetrue 的默认值仅出于向后兼容的原因 as described here

【讨论】:

  • 好点。我们的项目是 4.5,而我们的配置中的 targetFramework 是 4.5。我们现在已经在十页左右的页面中实现了异步并且它正在工作。问题是我们的两个页面需要在对同一响应进行异步调用后执行重定向。现在试图找出测试项目和我们的项目之间的差异。感谢您的回复。
  • 我几乎不想问这个问题,但你确实将Page.Async 设置为true,对吧?
  • 另一个有效的问题。是的,我愿意。
  • 不。我没有。出于某种原因,我在脑海中认为 false 是默认设置,并且我曾一度尝试使用 true 。我已经在我们的实时页面之一中实现了它,这似乎也很高兴。有时最简单的事情最容易被忽视。非常感谢!我会将您的答案标记为正确。
【解决方案2】:

我使用的 hack 是:

  1. 我在编写 API 调用方法的类中使用了静态字典 var d= new Dictionary&lt;string, bool&gt;();

  2. 我将代码行 client.timeout = new System.TimeSpan(0,0,60); 用于 API 发送请求。

  3. 当 API 超时时,它会抛出 TaskTimeoutException,在 TaskTimeoutExceptioncatch 块中写入代码为 d.Add("timeout", true);

  4. 现在,我创建了自定义操作过滤器并应用了以下代码:

    public class MyCustomActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if(MyApiClass.d.ContainsKey("timeout") && d["timeout"])
            {
                throw new Exception();
            }
        }
    }
    
  5. 我在操作上应用了[MyCustomActionFilter ]

  6. 当执行操作并进入自定义过滤器时,它会通过检查字典条目来引发异常。

  7. 如果发生超时,那么字典条目将为真,因此,在此基础上,我们检查条目并抛出异常。现在,我们在 Global.asax.cs 中有 Application_Error() 捕获异常。

  8. Application_Error() 中我们编写了重定向到所需页面的代码。

注意:在第 4 步中,您可以创建自定义异常以提供更精确的日志记录详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2010-10-08
    • 2021-04-04
    相关资源
    最近更新 更多