如何在 C# 中等待多个可能未初始化的任务?

kor*_*ral 2 c# task async-await

我有一个 API POST 端点创建一个资源,该资源可能有多个关系。为了确保首先使用有效关系创建资源,我需要检查给定的 ID 是否存在。有多个这样的关系,我不想依次等待每个关系。这是我的代码:

[HttpPost]
public async Task<ActionResult<Person>> PostPerson(Person person)
{
    ValueTask<Person> master, apprentice;
    ValueTask<Planet> planet;
    ValueTask<Models.LifeFormType> lifeFormType;
    if (person.MasterId.HasValue)
    {
        master = _context.People.FindAsync(person.MasterId);
    }
    

    if (person.ApprenticeId.HasValue)
    {
        apprentice = _context.People.FindAsync(person.ApprenticeId);
    }

    if (person.FromPlanetId.HasValue)
    {
        planet = _context.Planets.FindAsync(person.FromPlanetId);
    }

    if (person.LFTypeId.HasValue)
    {
        lifeFormType = _context.LifeFormTypes.FindAsync(person.LFTypeId);
    }
    List<ValueTask> tasks = new List<ValueTask> {master, apprentice, planet, lifeFormType};

    // if the above worked I'd process the tasks as they completed and throw errors
    // if the given id was not found and such
    
    _context.Attach(person);
    // _context.People.Add(person);
    await _context.SaveChangesAsync();

    return CreatedAtAction("GetPerson", new { id = person.Id }, person);
}
Run Code Online (Sandbox Code Playgroud)

如此处所示,我想等待列表[master,apprentice,planet,lifeFormType]完成,但在创建列表期间出现错误Local variable 'master' might not be initialized before accessing。因此,我在每次检查中尝试检查资源是否具有创建else块的值,并以某种方式添加ValueTask.CompletedTask如下内容:

if (person.MasterId.HasValue)
{
    master = _context.People.FindAsync(person.MasterId);
}
else
{
    master = ValueTask.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)

但后来我收到一条错误消息Cannot convert source type 'System.Threading.Tasks.ValueTask' to target type 'System.Threading.Tasks.ValueTask<Models.Person>'

这个怎么做?我想我现在只会等待每一个请求。

Alu*_*dad 6

您可以通过master在声明站点进行初始化来避免这种情况。

最简单的方法是使用default关键字。

ValueTask<Person> master = default;
Run Code Online (Sandbox Code Playgroud)

  • `await Task.WhenAll(master.AsTask(), apprentice.AsTask(),planet.AsTask(), lifeFormType.AsTask());` 这终于成功了。 (3认同)