ASP.Net控制器动作仅在任务完成后返回

时间:2014-10-01 19:25:25

标签: c# asp.net asp.net-mvc asp.net-mvc-5 task-parallel-library

 public ActionResult Favorites()
    {
        var favs = new List<Article>();
        var tFavs = new Task(() =>
        {
            favs = _favorites.GetFavorites(_currentUserId).ToList();
        });
        tFavs.Start();
        if (tFavs.IsCompleted)
        {
            ViewBag.Content = favs;
        }
        return View();
    }

在上面的代码中,如何确保仅在任务完成后调用返回View?目前,它会在视图上引发错误,因为ViewBag.Content为null。

2 个答案:

答案 0 :(得分:1)

您可以使用Taskawait执行此类操作:

public async Task<ActionResult> Favorites()
{

  ViewBag.Content = await _favorites.GetGetFavoritesAsync(_currentUserId).ToListAsync();
  return View();
}

GetFavoritesAsync()将如下所示:

public async Task<List<Article>> GetFavoritesAsync(int currentUserId)
{
   var query = from a in db.Articles
               where a.UserId = currentUserId
               select a;

   List<Article> articles = await query.ToListAsync();
   return articles;
}

有关创建异步操作的详细信息,请阅读Creating Asynchronous Actions in ASP.NET MVC

答案 1 :(得分:0)

Asker在其中一条评论中发布了以下内容:

  

如果我在并行运行的同一个操作中有多个任务,如果我必须在返回视图之前等待它们完成,那该怎么办?

因此我更新了我的原始答案并取消删除它,请参阅下面的代码,因为我相信在特定情况下这种方法是可行的。

public ActionResult Favorites()
{
    // Create and start all tasks first.
    var tFavs = new Task<List<Article>>(() =>
        _favorites.GetFavorites(_currentUserId).ToList());
    tFavs.Start();
    var task2 = new Task<SomeType>(() => new SomeType());
    task2.Start();

    // Wait for the results.
    ViewBag.Content = tFavs.Result;
    ViewBag.Content2 = task2.Result;
    return View();
}

如果任务之间存在依赖关系,那么您可以轻松地创建死锁,因为使用Result所以请注意这一点。

但是,当然,当您期望长时间运行的Web服务调用时,您可能希望进行异步操作。然后Ehsan Sajjad提供的答案是正确答案。