C#Task.Run表示System.Threading.Tasks.UnwrapPromise`1 [System.Threading.Tasks.VoidTaskResult]

时间:2019-02-08 05:00:35

标签: c# asp.net-core async-await

美好的一天,

我正在努力获取自己的价值。但是我遇到的结果是System.Threading.Tasks.UnwrapPromise 1 [System.Threading.Tasks.VoidTaskResult]`

这是我的示例代码:

public string GetStatusName(int empId){
    var status = Task.Run(async () =>
    {
        return await myRepo.GetStatus().Where(x=>x.EmpId == empId).Select(x => x.status).FirstOrDefaultAsync();
    });

    return status.ToString();
}

结果应该是状态的名称,但显示方式会有所不同。

我尝试在.Result()中使用return status.Result().ToString(),但是它锁定了UI线程,因此,获取一千条记录大约需要一分钟。

注意:给定的方法不应按照要求异步。因此我将Task.Run...放入了我的方法中,以便能够从回购中创建异步请求

我在此代码内使用GetStatusName()

public async Task<IEnumerable<EmployeeDto>> GetAll(){
    var employees = await getFromRepo.Employees();

    return employees.Select(x=>new EmployeeDto{
        ...
        Status = GetStatusName(x.EmpId)
        ...
    }).GroupBy(x=>new{
        x.EmployeeId
    }).Select(x=>x.First)).ToList();
}

我尝试了此操作,以使GetStatusName异步并尝试了以下代码:

return employees.Select(async x=>new EmployeeDto{
    ...
    Status = await GetStatusName(x.EmpId)
    ...
}).GroupBy(x=>new{
    x.EmployeeId
}).Select(x=>x.First)).ToList();

但是我在.GroupBy(...)中遇到错误,说Anonymous Types和类似Can't resolve symbol EmployeeId

请帮忙吗?

3 个答案:

答案 0 :(得分:2)

  

给定的方法不应该按照要求异步。

我建议您更改要求并转到async all the way

在您的情况下,理想情况下,您希望通过在初始员工查找中包括员工状态来避免辅助数据库查找。 Entity Framework has built-in support for this,尽管似乎您的数据库架构可能首先需要做一些工作(即,为什么在单独的表中按员工ID索引状态名称?)。

由于该解决方案更为详细,所以现在暂时搁置它,然后看看第二好的解决方案。您需要执行辅助数据库查找,并且应该进行async。这样的事情应该起作用:

public async Task<string> GetStatusNameAsync(int empId) {
  return await myRepo.GetStatus().Where(x=>x.EmpId == empId).Select(x => x.status).FirstOrDefaultAsync().ConfigureAwait(false);
}

public async Task<IEnumerable<EmployeeDto>> GetAll(){
  var employees = await getFromRepo.Employees();
  var statuses = new List<string>();
  foreach (var employee in employees)
    statuses.Add(await GetStatusNameAsync(employee.EmpId));

  return employees.Select((x, i) => new EmployeeDto {
    ...
    Status = statuses[i],
    ...
  }).GroupBy(x => new {
    x.EmployeeId
  }).Select(x=>x.First)).ToList();
}

我只建议将其作为临时解决方案,以等待更好的数据库架构和/或ORM映射。

答案 1 :(得分:0)

您可以像这样简化您的方法:

public async Task<string> GetStatusName(){
    return await myRepo.GetStatus().Select(x => x.status).FirstOrDefaultAsync();
}

答案 2 :(得分:0)

避免混合同步和异步调用。

引用Async/Await - Best Practices in Asynchronous Programming

使方法完全异步

public Task<string> GetStatusNameAsync(int empId) {
    return myRepo.GetStatus()
        .Where(x => x.EmpId == empId)
        .Select(x => x.status)
        .FirstOrDefaultAsync();
}

等待它

public async Task<IEnumerable<EmployeeDto>> GetAll(){
    var employees = await getFromRepo.Employees();
    var tasks = employees
        .GroupBy(_ => _.EmpId)
        .Select(async x => new EmployeeDto {
            Status = await GetStatusNameAsync(x.Key), //<--
            //...
        }).ToArray();

    var results = await Task.WhenAll(tasks);

    return results.ToList();
}