在 ASP.NET MVC 3 Action 方法中并行运行任务

发布于 2024-10-31 01:09:32 字数 1056 浏览 1 评论 0原文

我在 ASP.NET MVC 3 应用程序中有一个搜索操作,它返回包含给定关键字的建议和建议:

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    var containing = (from s in _readonlySession.All<Suggestion>()
                      from k in keywords
                      where (s.Text.ToLower().Contains(k.ToLower()))
                      orderby s.Text
                      select s).Distinct();

    var tagged = (from t in _readonlySession.All<Tag>()
                  from s in t.Suggestions
                  from k in keywords
                  where t.Text.ToLower().Contains(k.ToLower())
                  orderby s.Text
                  select s).Distinct();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

我认为包含和标记查询可以完美地并行运行。

同时触发这两个查询、等待结果并仅在两个查询完成时才返回的最佳方法是什么?

I have a Search action in an ASP.NET MVC 3 app that returns suggestions containing and suggestions tagged with the given keywords:

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    var containing = (from s in _readonlySession.All<Suggestion>()
                      from k in keywords
                      where (s.Text.ToLower().Contains(k.ToLower()))
                      orderby s.Text
                      select s).Distinct();

    var tagged = (from t in _readonlySession.All<Tag>()
                  from s in t.Suggestions
                  from k in keywords
                  where t.Text.ToLower().Contains(k.ToLower())
                  orderby s.Text
                  select s).Distinct();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

I think the containing and tagged queries could be perfectly run in parallel.

What is the best way to fire these two queries at the same time, wait for the results, and return only when both queries are completed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等待我真够勒 2024-11-07 01:09:32

任务并行库是您的最佳选择。通过 Google 可以获得大量信息,但以下是您的实现可能的样子。

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    IEnumerable containing=null;
    Task t1 = Task.Factory.StartNew(() =>
    {
        containing = (from s in _readonlySession.All<Suggestion>()
                        from k in keywords
                        where (s.Text.ToLower().Contains(k.ToLower()))
                        orderby s.Text
                        select s).Distinct().ToList();

    });

    IEnumerable tagged=null;
    Task t2 = Task.Factory.StartNew(() =>
    {
        var tagged = (from t in _readonlySession.All<Tag>()
                        from s in t.Suggestions
                        from k in keywords
                        where t.Text.ToLower().Contains(k.ToLower())
                        orderby s.Text
                        select s).Distinct().ToList();
    });

    t1.Wait();
    t2.Wait();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

请记住,如果您的应用程序收到大量请求,您最好不要异步执行查询 - 消耗 2 个额外线程来服务一个请求会占用其他传入请求的资源。只有当您的流量很大或者您的硬件不足时,这才会成为问题。

The Task Parallels Library is your best option. Plenty of information via Google, but below is what your implementation might look like.

[HttpPost]
public ActionResult Search(string query, int pg = 0)
{
    var keywords = query.Split(new[] { ' ', ',', ';' }, 
        StringSplitOptions.RemoveEmptyEntries);

    IEnumerable containing=null;
    Task t1 = Task.Factory.StartNew(() =>
    {
        containing = (from s in _readonlySession.All<Suggestion>()
                        from k in keywords
                        where (s.Text.ToLower().Contains(k.ToLower()))
                        orderby s.Text
                        select s).Distinct().ToList();

    });

    IEnumerable tagged=null;
    Task t2 = Task.Factory.StartNew(() =>
    {
        var tagged = (from t in _readonlySession.All<Tag>()
                        from s in t.Suggestions
                        from k in keywords
                        where t.Text.ToLower().Contains(k.ToLower())
                        orderby s.Text
                        select s).Distinct().ToList();
    });

    t1.Wait();
    t2.Wait();

    var model = new SearchViewModel
    {
        Query = query,
        Containing = containing.ToList(),
        Tagged = tagged.ToList()
    };

    return View(model);
}

Bear in mind that if your application gets a lot of requests, you may be better off not performing your queries asynchronously - consuming 2 extra threads to service one request takes resources away from other incoming requests. This will only be an issue if you have a huge volume of traffic, or if your hardware is inadequate.

世界等同你 2024-11-07 01:09:32

您在网页中使用 TPL 时要小心,因为 TPL 将利用原本用于服务其他 HTTP 请求的线程。本质上,您可以权衡单个请求的较低响应延迟与请求总体吞吐量的降低。

有关权衡的更多说明,请参阅以下文章:

http: //blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx

You want to be careful using the TPL from within a web page as the TPL will utilize threads that would otherwise be used servicing other HTTP requests. Essentially you can trade off lower response latency on individual requests against reduced overall throughput of requests.

See the following post for more explanation of the tradeoffs:

http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx

情独悲 2024-11-07 01:09:32

这可能是异步控制器的良好候选者。关于异步控制器的重要一点是,如果您想在这种情况下获得净性能增益,您需要修改存储库层并提供两种方法的异步版本,这两种方法在与远程系统(例如,一个数据库。

public class SearchController: AsyncController
{
    public void SearchAsync(string query, int pg = 0)
    {
        // TODO: Write a custom model binder to do this job
        // and have your controller action directly take an
        // IEnumerable<string> argument.
        var keywords = query.Split(new[] { ' ', ',', ';' }, 
            StringSplitOptions.RemoveEmptyEntries);

        AsyncManager.OutstandingOperations.Increment();
        AsyncManager.OutstandingOperations.Increment();

        _readonlySession.GetContainingCompleted += (sender, e) =>
        {
            AsyncManager.Parameters["containing"] = e.Value;
            AsyncManager.OutstandingOperations.Decrement();
        };

        _readonlySession.GetTaggedCompleted += (sender, e) =>
        {
            AsyncManager.Parameters["tagged"] = e.Value;
            AsyncManager.OutstandingOperations.Decrement();
        };

        _readonlySession.GetContainingAsync(keywords);
        _readonlySession.GetTaggedAsync(keywords);

        AsyncManager.Parameters["query"] = query;
    }

    public ActionResult SearchCompleted(string query, IEnumerable<Suggestion> containing, IEnumerable<Tag> tagged)
    {
        var model = new SearchViewModel
        {
            Query = query,
            Containing = containing.ToList(),
            Tagged = tagged.ToList()
        };
        return View(model);
    }
}

That may be a good candidate for an async controller. The important thing about async controllers is that if you want to have a net performance gain in this case you need to modify your repository layer and provide asynchronous versions of the two methods which ideally use I/O Completion ports when communicating with remote systems such as a database.

public class SearchController: AsyncController
{
    public void SearchAsync(string query, int pg = 0)
    {
        // TODO: Write a custom model binder to do this job
        // and have your controller action directly take an
        // IEnumerable<string> argument.
        var keywords = query.Split(new[] { ' ', ',', ';' }, 
            StringSplitOptions.RemoveEmptyEntries);

        AsyncManager.OutstandingOperations.Increment();
        AsyncManager.OutstandingOperations.Increment();

        _readonlySession.GetContainingCompleted += (sender, e) =>
        {
            AsyncManager.Parameters["containing"] = e.Value;
            AsyncManager.OutstandingOperations.Decrement();
        };

        _readonlySession.GetTaggedCompleted += (sender, e) =>
        {
            AsyncManager.Parameters["tagged"] = e.Value;
            AsyncManager.OutstandingOperations.Decrement();
        };

        _readonlySession.GetContainingAsync(keywords);
        _readonlySession.GetTaggedAsync(keywords);

        AsyncManager.Parameters["query"] = query;
    }

    public ActionResult SearchCompleted(string query, IEnumerable<Suggestion> containing, IEnumerable<Tag> tagged)
    {
        var model = new SearchViewModel
        {
            Query = query,
            Containing = containing.ToList(),
            Tagged = tagged.ToList()
        };
        return View(model);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文