参考自:http://www.codeguru.com/csharp/.net/net_asp/mvc/working-with-asynchronous-operations-in-asp.net-mvc.htm

 

   ASP.NET MVC 4加入了async关键词,使得异步编程变得很容易,但本文不是关于这个的,而是关于另外一个我没见过的实现ASP.NET MVC异步编程的方法,我估计很多人也没见过,所以我称之为Dark Magic(不常见但可能比较强大的东东)。

   先看一段代码:

public void Foo() {
   A();
   B();
   C();
}

 

   A()、B()、C()如果是远程方法调用,且三个方法互不影响,那么Foo()方法执行完成的时间就等于三个方法执行的时间之和,因为三个方法串行执行。

   这时就是异步编程大放光彩的时候了,如果采用异步编程,那么Foo()方法执行完成的时间等于A、B、C三个方法的执行时间的最大值。

   直入主题,ASP.NET MVC中如何异步编程实现呢(不考虑ASP.NET MVC 4的async)?

   上代码:

public class HomeController: AsyncController
{
   public void IndexAsync()
   {

   }

   public ActionResult IndexCompleted(...)
   {

   }
}

   

   观察下,控制器HomeController继承自AsyncController,并且多了两个Action。第一个Action名称后缀必需为Async,在这个Action方法里执行异步操作。第二个Action以Completed结尾,表示异步操作执行完成后做的事情。

   假设我们现在要实现一个获取Google RSS News和MSN RSS News的应用,代码大概如下:

public class HomeController : AsyncController
{
    private void GetGoogleNews()
    {
    }
 
    private void GetMSNNews()
    {
    }
 
    public void IndexAsync()
    {
    }
 
    public ActionResult IndexCompleted()
    {
    }
}

   很明显,获取Google News和MSN News这两个任务可以异步执行。

   IndexAsync的实现如下:

public void IndexAsync()
{
    AsyncManager.OutstandingOperations.Increment(2);
    Task.Factory.StartNew(() => GetGoogleNews()); 
    Task.Factory.StartNew(() => GetMSNNews()); 
}

   有点奇特,只说下第一行代码,Increment(2)表明还有2个异步任务待执行。

   GetGoogleNews和GetMSNNews的实现如下:

private void GetGoogleNews()
{
    XmlReader reader = XmlReader.Create("http://news.google.co.in/news?pz=1&cf=all&ned=in&hl=en&output=rss");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    reader.Close();
    AsyncManager.Parameters.Add("GoogleNews", formatter.Feed.Items);
    AsyncManager.OutstandingOperations.Decrement();
}
 
private void GetMSNNews()
{
    XmlReader reader = XmlReader.Create("http://msn.com/rss/news.aspx");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    reader.Close();
    AsyncManager.Parameters.Add("MSNNews", formatter.Feed.Items);
    AsyncManager.OutstandingOperations.Decrement();
}

   关注AsyncManager.Parameters.Add(...),它使用了AsyncManager对象的参数集合来保存异步任务执行完成后的结果数据。

   然后AsyncManager.OutstandingOperations.Decrement()方法用来表示待执行的异步任务又完成了一个。

   之后是IndexCompleted的实现:

public ActionResult IndexCompleted(IEnumerable<SyndicationItem> GoogleNews, IEnumerable<SyndicationItem> MSNNews)
{
    List<SyndicationItem> allItems = new List<SyndicationItem>();
    allItems.AddRange(GoogleNews);
    allItems.AddRange(MSNNews);
    allItems.Sort(CompareDates);
    ViewBag.FeedItems = allItems;
    return View();
}

   注意这里的参数IEnumerable<SyndicationItem> GoogleNews和IEnumerable<SyndicationItem> MSNNews,它们分别对应上面AsyncManager对象的参数结合中保存的两个结果数据。

   最后是前台代码实现了:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%@ Import Namespace="System.ServiceModel.Syndication" %>
 
<!DOCTYPE html>
 
<html>
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    <table border="1" cellpadding="6" cellspacing="0">
    <tr><th>Latest News from Google and MSN</th></tr>
    <%foreach (SyndicationItem item in ViewBag.FeedItems)
      {%>
      <tr><td><a href="<%= item.Links[0].Uri %>"><%= item.Title.Text %></a></td></tr>
    <%}%>
    </table>
    </div>
</body>
</html>

   访问时输入类似下面的URL即可:

http://localhost:4078/home/index

   自强不息,奋斗不止!

  

  

   

posted on 2012-12-29 02:03  feichexia  阅读(516)  评论(0编辑  收藏  举报