在启动期间,我需要获取两组数据的应用程序,每个数据都有其异步方法。如果我逐个调用它们,那么第二个调用只有在完成第一个调用后才会通过。
List<DataOne> DataCollectionOne;
List<DataTwo> DataCollectionTwo;
async void GetDatas()
{
if(sameCondOne)
DataCollectionOne = await GetDataOne();
if(sameCondTwo)
DataCollectionTwo = await GetDataTwo();
}
所以我将它们包装在任务调用中。
void GetDatas()
{
if(sameCondOne)
Task.Run(() => RunDataOne());
if(sameCondTwo)
Task.Run(() => RunDataTwo());
}
async void RunDataOne()
{
DataCollectionOne = await GetDataOne();
}
async void RunDataTwo()
{
DataCollectionTwo = await GetDataTwo();
}
我做得对吗?
答案 0 :(得分:9)
没有。您不需要,也不想启动新线程只是为了负责启动这两个异步操作。只需启动这两个操作(调用方法就是启动操作的方法)并且在您启动它们之前不要等待:
var firstTask = GetDataOne();
var secondTask = GetDataTwo();
var firstResult = await firstTask;
var secondResult = await secondTask;
要处理条件检查,只需有条件地启动任务,然后有条件地分配结果:
Task<T> firstTask = null;
if(shouldGetFirstTask)
firstTask = GetDataOne();
Task<T> secondTask = null;
if(shouldGetSecondTask)
secondTask = GetDataTwo();
if(firstTask != null)
DataCollectionOne = await firstTask;
if(secondTask != null)
DataCollectionTwo = await secondTask;
答案 1 :(得分:3)
首先,你应该避免返回async
方法(Best Practices in Asynchronous Programming)。
通常情况下,使用异步(或 TaskAsync ,如果已存在异步后缀方法)后缀async
方法。
如果我理解正确,你想要产生一些条件异步相互依赖的任务,并等待所有任务结束而不让任何一个等待另一个任务。
由于你正在对编排方法中的任务结果做任何事情,但你需要一些副作用,我会将 Get~ 方法包装成运行〜像你这样的方法。
您可以在 Run〜方法中测试条件(通过显式测试条件或将其作为参数):
async Task RunDataOneAsymc()
{
if (sameCondOne)
{
DataCollectionOne = await GetDataOneAsync();
}
}
但如果条件为假,这仍然会产生不必要的任务。因此,最好将其保持在呼叫方:
async Task RunDataOneAsymc()
{
DataCollectionOne = await GetDataOneAsync();
}
// ...
if (sameCondOne)
{
await RunDataOneAsymc();
}
在编排方法中,如果条件为真,您将生成任务,然后等待所有任务完成:
async Task RunAll()
{
var tasks = new List<Task>();
if (sameCondOne)
{
await RunDataOneAsymc();
}
// ...
if (sameCondN)
{
await RunDataNAsymc();
}
await Task.WhenAll(tasks);
}