我正在尝试编写多线程搜索,然后在任务完成后显示所有结果,但目前我还不了解如何在所有任务完成后处理结果
我的代码如下:
private async void DoSearchAsync()
{
var productResults = await SearchProductsAsync(CoreCache.AllProducts);
var brochureResults = await SearchBrochuresAsync(CoreCache.AllBrochures);
_searchResults.AddRange(productResults);
_searchResults.AddRange(brochureResults);
ResultsCount = _searchResults.Count;
}
_searchResults
是List<SearchResult>
我的理解是它会同时进行两种等待,然后将产品添加到搜索结果中。但是,当我在我的控制器中调用它时:
public ActionResult Index(string searchText)
{
SearchHelper helper = new SearchHelper(searchText);
helper.DoSearchAsync();
return View(helper);
}
在搜索完成之前显示页面,因此没有显示任何结果。如何在显示页面之前等待结果完成?
我已经查看Tasks.Wait
,但不知道如何将其应用于上述内容,因为它需要一系列任务
private Task<List<SearchResult>> SearchProductsAsync(IEnumerable<Product> products)
{
return Task<List<SearchResult>>.Factory.StartNew(() => GetProducts(products));
}
private Task<List<SearchResult>> SearchBrochuresAsync(IEnumerable<Assets> brochures)
{
return Task<List<SearchResult>>.Factory.StartNew(() => GetBrochures(brochures));
}
答案 0 :(得分:13)
每次在ASP.NET控制器中调用Factory.StartNew
或Task.Run
时,都会从ThreadPool
获取一个帖子。该线程可以以其他方式提供另一个传入的HTTP请求。因此,您的网络应用可扩展性确实受到了损害。这可能是一个严重的问题,具体取决于您的Web应用程序预计会收到多少并发HTTP请求。
你还好吗?如果是这样,代码可能如下所示:
private async Task DoSearchAsync()
{
var productResults = SearchProductsAsync(CoreCache.AllProducts);
var brochureResults = SearchBrochuresAsync(CoreCache.AllBrochures);
await Task.WhenAll(productResults, brochureResults);
_searchResults.AddRange(productResults.Result);
_searchResults.AddRange(brochureResultsbrochure.Results);
ResultsCount = _searchResults.Count;
}
public async Task<ActionResult> Index(string searchText)
{
SearchHelper helper = new SearchHelper(searchText);
await helper.DoSearchAsync();
return View(helper);
}
注意我已为async void
将async Task
更改为DoSearchAsync
,并将控制器方法设为async
,因此返回Task<ActionResult>
。
答案 1 :(得分:1)
我的理解是,它将同时进行两项等待
这是不正确的皮特。 await意味着它将暂停当前方法的执行,直到被调用的Async方法完成为止。因此,您的2次搜索将无法并行运行。
有关说明,请参阅the first line of the MSDN documentation ....
await运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。
您应该使用Task.WhenAll等待两个搜索完成。由于WhenAll支持返回Task<T>
并且两个异步搜索都返回List<SearchResult>
,您可以将两个搜索的结果组合在一起,并在一个语句中等待它们......
var searchProducts = Task.Factory.StartNew(() => GetProducts(CoreCache.AllProducts));
var searchBrochure = Task.Factory.StartNew(() => GetBrochures(CoreCache.AllBrochures));
var allResults = await Task.WhenAll(new [] { searchProducts, searchBrochure });
//allResults is List<SearchResult>[]
为了完整性,值得注意的是allResults将包含2个结果集。它不会在2套上执行联合。
可以找到LinqPad的完整工作示例here on GitHub
答案 2 :(得分:0)
您可以使用任务工厂,然后对生成的任务调用wait:
Task taskA = Task.Factory.StartNew(() => DoSomeWork(10000000));
taskA.Wait();
Console.WriteLine("taskA has completed.");
http://msdn.microsoft.com/en-us/library/dd537610(v=vs.110).aspx
答案 3 :(得分:0)
你可以让它在显示页面之前等待结果完成,方法是让你的函数不要异步。
或者,如果您想要异步,可以移动搜索功能,以便在加载页面时触发的AJAX调用调用
答案 4 :(得分:0)
您需要等待该功能完成。为了做到这一点,首先让它返回一个任务:
private async Task DoSearchAsync()
等待它:
public async Task<ActionResult> Index(string searchText)
{
SearchHelper helper = new SearchHelper(searchText);
await helper.DoSearchAsync();
return View(helper);
}
有关详细信息,请参阅http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4