Не все пути кода возвращают значение при задаче

#c#

Вопрос:

Мне нужно дождаться завершения всей задачи, а затем вернуть значение. Мой код выдает ошибку «Не все пути кода возвращают значение». Не могли бы вы показать мне, как это исправить? Я действительно запутался в задачах.

  public async override Task<TagInfoReply> GetInfo(TagInfoRequest request, ServerCallContext context)
        {
            var tagInfo = JsonSerializer.Deserialize<TagInfo>(request.TagInfo);
            var parameter = JsonSerializer.Deserialize<ParameterGetWhiteListWithEntryInfo>(request.DetectedTag);
            var task = Task.Run(() =>
            {
                return filters.FilterTags(tagInfo);
            });
            await task.ContinueWith(
                    async antecedent =>
                    {
                        if (antecedent.Result)
                        {
                            var reply = await pcs.GetTagInfo(parameter, tagInfo, TagFilterTime);
                            return new TagInfoReply
                            {
                                FetchedTagInfo = reply
                            };
                        }
                        else
                        {
                            return new TagInfoReply
                            {
                                FetchedTagInfo = string.Empty
                            };
                        }
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }
 

Если я введу

 return new TagInfoReply
                                {
                                    FetchedTagInfo = string.Empty
                                };
 

в самом конце и вне задачи.Продолжайте, хорошо, ошибка исчезает, но проблема в том, что при запуске она не ожидает завершения задачи. Он переходит непосредственно к последнему возвращению.

Комментарии:

1. Вы не возвращаете результат из GetInfo любого места, которое я вижу? Решение: вернуть результат из GetInfo .

2. Это то, что я пытаюсь выяснить. У меня есть операторы return в моей задаче. Продолжайте, я думаю, что этого достаточно. Как я уже сказал, я действительно путаюсь в задачах.

3. Эти операторы возврата находятся в анонимном методе, к которому вы переходите ContinueWith . Они возвращаются из анонимного метода в вызывающий код внутри ContinueWith .

4. На самом деле я вроде как понимаю эту часть. «Эти операторы возврата находятся в анонимном методе, который вы передаете ContinueWith. Они возвращаются из анонимного метода в вызывающий код внутри ContinueWith. «. Как мне сделать так, чтобы он ожидал завершения задачи, а затем возвращал ее результат. В моем «Редактировании» я сказал, что он переходит непосредственно к последнему возврату, не дожидаясь завершения задачи.

5. Ваш текущий код может быть переписан путем замены анонимного метода на реальный, подобный этому .

Ответ №1:

На данный момент ваш return код возвращается только из анонимного метода, которому вы передали ContinueWith , и они возвращаются к вызывающему коду внутри ContinueWith . На самом деле вы ничего не возвращаете GetInfo .

Результат ContinueWith становится доступным вам как его результат, поэтому вы должны иметь возможность переписать свой код следующим образом:

 public async override Task<TagInfoReply> GetInfo(TagInfoRequest request, ServerCallContext context)
{
    var tagInfo = JsonSerializer.Deserialize<TagInfo>(request.TagInfo);
    var parameter = JsonSerializer.Deserialize<ParameterGetWhiteListWithEntryInfo>(request.DetectedTag);
    var task = Task.Run(() =>
    {
        return filters.FilterTags(tagInfo);
    });
    return await task.ContinueWith(
            async antecedent =>
            {
                if (antecedent.Result)
                {
                    var reply = await pcs.GetTagInfo(parameter, tagInfo, TagFilterTime);
                    return new TagInfoReply
                    {
                        FetchedTagInfo = reply
                    };
                }
                else
                {
                    return new TagInfoReply
                    {
                        FetchedTagInfo = string.Empty
                    };
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
}
 

Комментарии:

1. Я тоже пробовал это раньше, но это дает мне ошибку «Поскольку это асинхронный метод, возвращаемое выражение должно иметь тип TagInfoReply, а не Task<TagInfoReply> . Поэтому я меняю возвращаемый тип на просто TagInfoReply , но это выдает ошибку «тип возвращаемого значения должен быть Task<TagInfoReply> . Я добавил «.Result» в «}, TaskContinuationOptions . Только при незавершенном завершении). Результат» Спасибо @Llama.

2. @Ibanez1408 Ты await где-нибудь удалил an?

3. Нет, я этого не делал, сэр…

4. @Ibanez Так у вас есть return await task.ContinueWith , и случайно не использовал return task.ContinueWith ?

5. Да, сэр. Я использовал return await task . Продолжайте с.

Ответ №2:

Суть вашей проблемы в том, что вам нужно вернуть значение. Побочная проблема заключается в том, что вы вообще не должны ее использовать ContinueWith . Если вы замените ContinueWith на await , ваш код станет намного понятнее:

 public async override Task<TagInfoReply> GetInfo(TagInfoRequest request, ServerCallContext context)
{
  var tagInfo = JsonSerializer.Deserialize<TagInfo>(request.TagInfo);
  var parameter = JsonSerializer.Deserialize<ParameterGetWhiteListWithEntryInfo>(request.DetectedTag);
  var result = await Task.Run(() =>
  {
    var filteredTags = filters.FilterTags(tagInfo);
    if (antecedent.Result)
    {
      var reply = await pcs.GetTagInfo(parameter, tagInfo, TagFilterTime);
      return new TagInfoReply
      {
          FetchedTagInfo = reply
      };
    }
    else
    {
      return new TagInfoReply
      {
          FetchedTagInfo = string.Empty
      };
    }
  });
  return resu<
}
 

Также вероятно, что вам не нужно Task.Run там:

 public async override Task<TagInfoReply> GetInfo(TagInfoRequest request, ServerCallContext context)
{
  var tagInfo = JsonSerializer.Deserialize<TagInfo>(request.TagInfo);
  var parameter = JsonSerializer.Deserialize<ParameterGetWhiteListWithEntryInfo>(request.DetectedTag);
  var filteredTags = filters.FilterTags(tagInfo);
  if (antecedent.Result)
  {
    var reply = await pcs.GetTagInfo(parameter, tagInfo, TagFilterTime);
    return new TagInfoReply
    {
        FetchedTagInfo = reply
    };
  }
  else
  {
    return new TagInfoReply
    {
        FetchedTagInfo = string.Empty
    };
  }
}