Task.WhenAny 只抓取解决最快的任务
Task.WhenAny to Grab Only Task that resolves the Fastest
我有两个异步方法,它们都是 return 一个列表。他们都以不同的方式搜索记录,我需要他们同时 运行,我只关心最先完成的任务。如果可能,应取消另一个。
我想我应该使用 Task.WhenAny 但似乎没有正确实现。下面的 GoAsync 实现没有 return 任何记录,它在 await 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);
请注意,我深陷其中,我需要并行 运行 这些任务以获得竞争结果。该例程作为签名
private static void DoVariousCalucualtions() {}
您不需要创建 new Task
,异步方法将 return 一个任务。
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 核心。这意味着您需要从控制器操作开始使整个 "methods pipeline" 异步。
如果您将使用 GoAsync().Result;
,您将陷入僵局,您已经经历过这种行为...
我有两个异步方法,它们都是 return 一个列表。他们都以不同的方式搜索记录,我需要他们同时 运行,我只关心最先完成的任务。如果可能,应取消另一个。
我想我应该使用 Task.WhenAny 但似乎没有正确实现。下面的 GoAsync 实现没有 return 任何记录,它在 await 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);
请注意,我深陷其中,我需要并行 运行 这些任务以获得竞争结果。该例程作为签名 private static void DoVariousCalucualtions() {}
您不需要创建 new Task
,异步方法将 return 一个任务。
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 核心。这意味着您需要从控制器操作开始使整个 "methods pipeline" 异步。
如果您将使用 GoAsync().Result;
,您将陷入僵局,您已经经历过这种行为...