C # Task.Run говорит System.Threading.Tasks.UnwrapPromise`1 [System.Threading.Tasks.VoidTaskResult] - PullRequest
0 голосов
/ 08 февраля 2019

Добрый день,

Я пытаюсь получить свою ценность.Но я получаю результат, который говорит: 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(), но он блокирует поток пользовательского интерфейса, поэтому выборка занимает тысячи минут для тысячи записей.

Примечание: данный метод не должен быть асинхронным согласно требованию.поэтому я поместил 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 голосов
/ 08 февраля 2019

Избегайте смешивания синхронных и асинхронных вызовов.

Ссылка Асинхронизация / ожидание - лучшие практики асинхронного программирования

Полностью сделайте метод асинхронным

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();
}
0 голосов
/ 08 февраля 2019

Данный метод не должен быть асинхронным в соответствии с требованием.

Я рекомендую изменить требования и пройти async до конца .

В вашем случае, в идеале вы хотели бы избежать вторичных поисков в БД, включив статусы сотрудников в первоначальный поиск сотрудников. Entity Framework имеет встроенную поддержку для этого , хотя кажется, что вашей схеме базы данных вначале может потребоваться некоторая работа (т. Е. Почему имена состояний в отдельной таблице индексируются по идентификатору сотрудника?).

Поскольку это решение более детально, давайте отложим его пока и посмотрим на второе лучшее решение.Вам нужно выполнить вторичный поиск в БД, и вы должны сделать их 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.

0 голосов
/ 08 февраля 2019

Вы можете упростить свой метод следующим образом:

public async Task<string> GetStatusName(){
    return await myRepo.GetStatus().Select(x => x.status).FirstOrDefaultAsync();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...