C# 在异步操作完成之前从方法返回的错误做法?

C# 在异步操作完成之前从方法返回的错误做法?,c#,asp.net,asynchronous,asp.net-web-api,async-await,C#,Asp.net,Asynchronous,Asp.net Web Api,Async Await,我有一个WebAPI2端点,在这里,我希望在检索和验证用户时异步执行操作。如果该用户不存在,我想返回一个404 not Found,如下所示: public async Task<IHttpActionResult> Get() { var getCatTask = GetCatAsync(); var user = await GetUserAsync(); if(user == null) { return NotFound();

我有一个WebAPI2端点,在这里,我希望在检索和验证用户时异步执行操作。如果该用户不存在,我想返回一个404 not Found,如下所示:

public async Task<IHttpActionResult> Get()
{
    var getCatTask = GetCatAsync();
    var user = await GetUserAsync();

    if(user == null)
    {
        return NotFound();
    }     

    var cat = await getCatTask;

    return Ok(cat);
}
公共异步任务Get() { var getCatTask=GetCatAsync(); var user=await GetUserAsync(); if(user==null) { 返回NotFound(); } var cat=等待getCatTask; 返回Ok(cat); } 如果用户等于null并且方法在不等待getCatTask的情况下返回,这是否会导致潜在的问题,或者这被认为是一种不好的做法

这并不是很糟糕,因为在这种情况下,您只读取数据,而忽略结果。对于每一个假请求,您都要承担额外的
GetCatAsync
操作的成本(这种情况可能不会经常发生)

如果可能的话,考虑<代码> GETCATASYNC < /C>可取消,然后至少可以在返回之前开始清理:

public async Task<IHttpActionResult> Get()
{
  var cts = new CancellationTokenSource();
  var getCatTask = GetCatAsync(cts.Token);
  var user = await GetUserAsync();

  if (user == null)
  {
    cts.Cancel();
    return NotFound();
  }     

  var cat = await getCatTask;
  return Ok(cat);
}
公共异步任务Get() { var cts=新的CancellationTokenSource(); var getCatTask=GetCatAsync(cts.Token); var user=await GetUserAsync(); if(user==null) { cts.Cancel(); 返回NotFound(); } var cat=等待getCatTask; 返回Ok(cat); }
这是完全可以接受的。在
async
await
方面,您没有做任何不正确的事情。关于关键字的一些注意事项:

async
关键字只是启用了
wait
关键字的使用。
wait
关键字是所有“魔法”发生的地方,即。;异步状态机将暂停方法执行,并在“等待的”异步操作完成时返回到该点

一个重要考虑:

GetCatAsync()
是否返回表示已启动的异步操作的
任务
任务
?如果是这样的话,这可能会有点问题,如果不是这样的话,你会没事的,因为这将在以后等待。不过我还是建议取消

public async Task<IHttpActionResult> Get()
{
    var cts = new CancellationTokenSource();
    var getCatTask = GetCatAsync(cts.Token);
    var user = await GetUserAsync();

    if (user == null)
    {
        cts.Cancel();
        return NotFound();
    }     

    var cat = await getCatTask;
    return Ok(cat);
}
公共异步任务Get() { var cts=新的CancellationTokenSource(); var getCatTask=GetCatAsync(cts.Token); var user=await GetUserAsync(); if(user==null) { cts.Cancel(); 返回NotFound(); } var cat=等待getCatTask; 返回Ok(cat); }
但是,斯蒂芬·克利里(Stephen Cleary)比我抢先一步——上面提到过。

我想出于性能原因,您可以在验证用户时开始获取数据(我不认为我会亲自这么做,因为如果在验证完成之前意外地开始向用户发送数据,会带来潜在的安全风险,但是如果您的仔细操作和额外的性能确实是必须的,那么可能)。但是,如果您返回“未找到”,则最好中止异步任务(因为这是在浪费处理器时间)。此外,由于数据无法个性化(用户未经验证),因此将“GetCat”缓存在某个位置而不是每次加载它不是更好吗。