Я относительно новичок в C#. Может кто-нибудь объяснить, что здесь происходит?
public List<InboundPlanSummary> GetListInboundPlans(ParameterGetListInboundPlans parameterGetListInboundPlans) =>
Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)).ConfigureAwait(false).GetAwaiter().GetResult();
Я потерялся здесь. Любая помощь с объяснением будет принята с благодарностью.
Похоже на попытку предоставить синхронную версию асинхронного метода GetListInboundPlansAsync. Обычно считается антишаблоном из-за риска взаимоблокировок. См. также stackoverflow.com/questions/59018541/… и stackoverflow.com/questions/40324300/…





Хорошо, давайте сделаем небольшой обзор, поскольку здесь собрано много всего.
public int MethodName(int a) => a+5;
Это то же самое, что
public int MethodName(int a)
{
return a + 5;
}
По сути, Method() => x; — это просто сокращение для возврата x. Чаще всего это используется, если значение повтора/его генерация представляет собой однострочник.
Итак, давайте воспользуемся этими знаниями для перевода вашего
public List<InboundPlanSummary> GetListInboundPlans(ParameterGetListInboundPlans parameterGetListInboundPlans) =>
Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)).ConfigureAwait(false).GetAwaiter().GetResult();
в
public List<InboundPlanSummary> GetListInboundPlans(ParameterGetListInboundPlans parameterGetListInboundPlans)
{
return Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)).ConfigureAwait(false).GetAwaiter().GetResult();
}
Теперь давайте посмотрим на
Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)).ConfigureAwait(false).GetAwaiter().GetResult()
Чтобы упростить задачу, я разделю их для вас.
var a = Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans));
var b = a.ConfigureAwait(false);
var c = b.GetAwaiter();
var x = c.GetResult();
Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)) Создает и запускает задачу. Эта задача выполняется GetListInboundPlansAsync(parameterGetListInboundPlans).
Поскольку это то же имя метода, только с добавлением async, мы можем предположить/заключить, что GetListInboundPlansAsync возвращает List<InboundPlanSummary>, но асинхронным способом.
Это означает, что то, что он возвращает, на самом деле не является полностью заполненным списком, а является задачей, которая все еще выполняет/заполняет этот список.
итак, наш a имеет тип Task<List<InboundPlanSummary>>
Чтобы побыстрее и для простоты, когда вы видите Task.Run(() => Meth()), игнорируйте часть () => и сосредоточьтесь на том, что будет дальше. Если вы хотите выполнить несколько задач за один запуск задачи, вы можете сделать это Task.Run(() => { //write like this is just a method})
ConfigureAwait(false) очень простыми словами определяет, что Задача/ожидание будет выполняться в другом потоке, а не в потоке, который его вызвал.
итак, наш b — это ConfiguredTaskAwaitable<List<InboundPlanSummary>>
GetAwaiter()ну вот и ожидающий Задания (это не так уж и важно)
и GetResult() получает результат задачи после ее завершения и завершает задачу/ожидание
Итак, скажем, у нас было var result = Task.Run(() => GetListInboundPlansAsync(parameterGetListInboundPlans)).ConfigureAwait(false).GetAwaiter().GetResult();
С учетом знаний, которые мы только что получили, мы можем сказать, что он делает следующее:
Задаче приказывают поставить ее в очередь GetListInboundPlansAsync и запустить ее асинхронно в другом потоке в Threadpool ConfigureAwait(false). Затем захватите ожидаемый GetAwaiter и извлеките результат GetResult, чтобы наш result имел тип List<InboundPlanSummary>
И этот результат затем возвращается.
Короче говоря: опубликованный вами метод позволяет вам синхронно запускать асинхронный метод GetListInboundPlansAsync и получать из него список.
«определяет, что Задача/ожидание будет выполняться в другом потоке» — это неправильно. Он определяет, что после ожидания задачи код может возобновиться в другом контексте синхронизации.
@KlausGütter, тогда я прошу прощения. Насколько я понял, когда вы запускаете его с true, он имеет возможность блокировать потоки, как, например, потоки пользовательского интерфейса. Я с радостью заменю эту ошибку. Есть ли способ, которым вы рекомендуете написать это, чтобы новички могли его понять?
Упомянутая вами блокировка является результатом использования GetAwaiter().GetResult() ожидания завершения задачи, пока задача ожидает продолжения в том же потоке. См., например. blog.stephencleary.com/2012/07/dont-block-on-async-code.html
=> — это лямбда-оператор, который в основном читается как «дано что-то, верните что-то» stackoverflow.com/questions/290061/…. Я предполагаю, что приведенная выше команда настраивает задачу, которая принимает список входящих планов и в конечном итоге возвращает результаты асинхронно.