我有两个异步方法都返回一个List。它们都以不同的方式搜索记录,我需要它们都以并行方式运行,并且我只关心首先完成的任务。如果可能,应取消另一个。
我认为我应该使用Task.WhenAny,但似乎并没有正确实现该实现。下面的GoAsync实现不返回任何记录,它在等待Task.WhenAny(taskList)行时跳出例程(无错误)。我没有结果,等等。如何获得结果?我能正确解决这个问题吗?
public static async void GoAsync(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
{
var taskList = new List<Task>();
taskList.Add(new Task(async () => await SearchRoutine1Async(search, cancellationToken)));
taskList.Add(new Task(async () => await SearchRoutine2Async( search, cancellationToken)));
Task completedTask = await Task.WhenAny(taskList);
}
异步例程是这样的:
public static async Task<List<SearchModel>> SearchRoutine1Async( SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
{
using (DBContext db = new DBContext)
{
var searchModels= await db.SearchModel
.Where(sm => sm.subKey1 = search.subKey1)
.ToListAsync(cancellationToken)
;
return searchModels;
}
}
当我尝试单独运行这些任务(例如这样做)时:它工作正常。
var callTask = Task.Run(() => SearchRoutine1Async(search));
callTask.Wait();
var list1 = callTask.Result;
var callTask2 = Task.Run(() => SearchRoutine2Async(search));
callTask2.Wait();
var list2 = callTask.Result;
[更新]: 我已根据以下答案之一将GoAsync更改为:(但仍无法正常工作)
public static async Task<List<SearchModel>> GoAsync(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
{
var taskList = new List<Task<List<SearchModel>>>
{
SearchRoutine1Async(search, cancellationToken),
SearchRoutine2Async(search, cancellationToken)
};
Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);
return completedTask.Result;
}
我从SYNCHRONOUS例程中调用该例程,如下所示:
var result = GoAsync(search);
请注意,我深陷于例程中,我需要并行运行这些任务才能获得竞争结果。该例行程序是 私有静态void DoVariousCalucualtions(){}
答案 0 :(得分:1)
您无需创建new Task
,异步方法将返回任务。
public static async Task GoAsync(
SearchContract search,
CancellationToken cancellationToken = default(CancellationToken))
{
var taskList = new List<Task<List<SearchModel>>>
{
SearchRoutine1Async(search, cancellationToken),
SearchRoutine2Async( search, cancellationToken)
};
Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);
// use competedTask.Result here (safe as you know task is completed)
}
问题更新后:
要获得结果,您需要等待功能完成。
var result = await GoAsync();
但是您提到此调用位于带有void
签名的同步函数的深处,并且您没有使用ASP.Net Core。这意味着您需要从控制器操作开始使整个“方法管道”异步。
如果您将使用GoAsync().Result;
,将最终陷入僵局,这是您已经经历的行为...