#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
};
}
}