【问题标题】:ASP.NET MVC AsyncController Exception HandlingASP.NET MVC AsyncController 异常处理
【发布时间】:2012-02-02 10:30:41
【问题描述】:

在 ASP.NET MVC 上,我尝试使用旧的异步编程模型(实际上是当前的,新的仍然是 CTP)编写一个异步控制器动作。

在这里,我尝试并行运行 4 个操作,效果很好。完整代码如下:

public class SampleController : AsyncController {

    public void IndexAsync() {

        AsyncManager.OutstandingOperations.Increment(4);

        var task1 = Task<string>.Factory.StartNew(() => {

            return GetReponse1();
        });
        var task2 = Task<string>.Factory.StartNew(() => {

            return GetResponse2();
        });
        var task3 = Task<string>.Factory.StartNew(() => {

            return GetResponse3();
        });
        var task4 = Task<string>.Factory.StartNew(() => {

            return GetResponse4();
        });

        task1.ContinueWith(t => {

            AsyncManager.Parameters["headers1"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        task2.ContinueWith(t => {

            AsyncManager.Parameters["headers2"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        task3.ContinueWith(t => {

            AsyncManager.Parameters["headers3"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        task4.ContinueWith(t => {

            AsyncManager.Parameters["headers4"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        task3.ContinueWith(t => {

            AsyncManager.OutstandingOperations.Decrement();

        }, TaskContinuationOptions.OnlyOnFaulted);
    }

    public ActionResult IndexCompleted(string headers1, string headers2, string headers3, string headers4) {

        ViewBag.Headers = string.Join("<br/><br/>", headers1, headers2, headers3, headers4);

        return View();
    }

    public ActionResult Index2() {

        ViewBag.Headers = string.Join("<br/><br/>", GetReponse1(), GetResponse2(), GetResponse3(), GetResponse4());

        return View();
    }
}

下面这些是异步操作正在运行的方法:

string GetReponse1() {

    var req = (HttpWebRequest)WebRequest.Create("http://www.twitter.com");
    req.Method = "HEAD";

    var resp = (HttpWebResponse)req.GetResponse();

    return FormatHeaders(resp.Headers);
}

string GetResponse2() {

    var req2 = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com");
    req2.Method = "HEAD";

    var resp2 = (HttpWebResponse)req2.GetResponse();

    return FormatHeaders(resp2.Headers);
}

string GetResponse3() {

    var req = (HttpWebRequest)WebRequest.Create("http://google.com");
    req.Method = "HEAD";

    var resp = (HttpWebResponse)req.GetResponse();

    return FormatHeaders(resp.Headers);
}

string GetResponse4() {

    var req = (HttpWebRequest)WebRequest.Create("http://github.com");
    req.Method = "HEAD";

    var resp = (HttpWebResponse)req.GetResponse();

    return FormatHeaders(resp.Headers);
}

private static string FormatHeaders(WebHeaderCollection headers) {

    var headerStrings = from header in headers.Keys.Cast<string>()
                        select string.Format("{0}: {1}", header, headers[header]);

    return string.Join("<br />", headerStrings.ToArray());
}

我这里还有Index2 方法,它是同步的并且做同样的事情。

我比较了两个操作的执行时间,有很大的不同(大约 2 秒)

但我认为我在这里遗漏了很多东西(异常处理、超时等)。我只在 task3 上实现异常处理,但我认为这不是正确的做法。

处理此类操作的异常最健康的方法是什么?

【问题讨论】:

标签: asp.net-mvc multithreading asp.net-mvc-3 asynchronous exception-handling


【解决方案1】:

在访问任务结果之前,您应该测试它是否成功完成。如果出现错误,您不应该尝试访问结果,而是对异常执行一些操作:

task1.ContinueWith(t => 
{
    if (!t.IsFaulted)
    {
        AsyncManager.Parameters["headers1"] = t.Result;
    }
    else if (t.IsFaulted && t.Exception != null)
    {
        AsyncManager.Parameters["error"] = t.Exception;
    }
    AsyncManager.OutstandingOperations.Decrement();
});

【讨论】:

  • 我现在明白了。当我故意抛出异常时,我试图访问任务的结果,这就是操作无休止地运行的原因。你认为我使用这种方法会 100% 安全并且能够抛出适当的异常吗?另外,您认为我是否应该在这里实现 AsyncTimeout 属性?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
相关资源
最近更新 更多