Во-первых, вы не можете иметь несколько элементов с одним и тем же идентификатором. Я знаю, что вы сказали, что не можете контролировать, как создается форма, но ... попытайтесь как-то удалить все идентификаторы из радиостанций или сделать их уникальными.
Чтобы получить значение выбранного радио , выберите его по имени с фильтром :checked
.
var selectedVal = "";
var selected = $("input[type='radio'][name='s_2_1_6_0']:checked");
if (selected.length > 0) {
selectedVal = selected.val();
}
EDIT
Таким образом, вы не контролируете имена. В этом случае я бы сказал, что эти переключатели находятся внутри div, названного, скажем, radioDiv
, а затем немного измените ваш селектор:
var selectedVal = "";
var selected = $("#radioDiv input[type='radio']:checked");
if (selected.length > 0) {
selectedVal = selected.val();
}
После использования WhenAll
вы можете вывести результаты по отдельности с помощью await
:
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
await Task.WhenAll(catTask, houseTask, carTask);
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
Вы также можете использовать Task.Result
(поскольку вы знаете, что к этому моменту все они завершены успешно). Однако я рекомендую использовать await
, потому что это явно правильно, в то время как Result
может вызвать проблемы в других сценариях.
Вы можете использовать Task.WhenAll
, как указано, или Task.WaitAll
, в зависимости от того, хотите ли вы, чтобы нить подождал. Взгляните на ссылку для объяснения того и другого.
Используйте Task.WhenAll
, а затем ждите результатов:
var tCat = FeedCat();
var tHouse = SellHouse();
var tCar = BuyCar();
await Task.WhenAll(tCat, tHouse, tCar);
Cat cat = await tCat;
House house = await tHouse;
Tesla car = await tCar;
//as they have all definitely finished, you could also use Task.Value.
Если вы используете C # 7, вы можете использовать удобный метод обертки, подобный этому ...
public static class TaskEx
{
public static async Task<(T1, T2)> WhenAll<T1, T2>(Task<T1> task1, Task<T2> task2)
{
await Task.WhenAll(task1, task2);
return (task1.Result, task2.Result);
}
}
..., чтобы включить удобный синтаксис, подобный этому, когда вы хотите ждать нескольких задач с разными типами возврата. Конечно, вам придется сделать несколько перегрузок для разного количества задач.
var (someInt, someString) = await TaskEx.WhenAll(GetIntAsync(), GetStringAsync());
Task.WhenAll()
не возвращает кортеж. Один из них создается из свойств Result
предоставленных задач после завершения задачи, возвращаемой Task.WhenAll()
.
– Chris Charabaruk
18 August 2017 в 23:20
Учитывая три задачи: FeedCat()
, SellHouse()
и BuyCar()
, есть два интересных случая: либо они все завершаются синхронно (по какой-то причине, возможно, кэширование или ошибка), либо они не делают.
Скажем, у нас есть вопрос:
Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = FeedCat();
Task<Tesla> z = FeedCat();
// what here?
}
. Теперь простой подход будет:
Task.WhenAll(x, y, z);
, но ... это не удобный для обработки результатов; мы обычно хотели бы await
, что:
async Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = FeedCat();
Task<Tesla> z = FeedCat();
await Task.WhenAll(x, y, z);
// presumably we want to do something with the results...
return DoWhatever(x.Result, y.Result, z.Result);
}
, но это делает много накладных расходов и выделяет различные массивы (включая массив params Task[]
) и списки (внутренне). Это работает, но это не очень хорошая ИМО. Во многих отношениях проще использовать операцию async
и только await
каждый по очереди:
async Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = FeedCat();
Task<Tesla> z = FeedCat();
// do something with the results...
return DoWhatever(await x, await y, await z);
}
Вопреки некоторым комментариям выше, использование await
вместо Task.WhenAll
делает не отличается от того, как выполняются задачи (одновременно, последовательно и т. д.). На самом высоком уровне Task.WhenAll
предшествует хорошей поддержке компилятора для async
/ await
и полезен , когда эти вещи не существовали . Это также полезно, когда у вас есть произвольный массив задач, а не 3 сдержанных задач.
Но: у нас все еще есть проблема, что async
/ await
генерирует много шума компилятора для продолжения , Если вероятность того, что задачи действительно завершится синхронно, , мы можем оптимизировать это, построив синхронный путь с асинхронным резервным копированием:
Task<string> DoTheThings() {
Task<Cat> x = FeedCat();
Task<House> y = FeedCat();
Task<Tesla> z = FeedCat();
if(x.Status == TaskStatus.RanToCompletion &&
y.Status == TaskStatus.RanToCompletion &&
z.Status == TaskStatus.RanToCompletion)
return Task.FromResult(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
async Task Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await x, await y, await z);
}
Этот «путь синхронизации с async fallback "становится все более распространенным, особенно в высокопроизводительном коде, где синхронные завершения относительно часты. Обратите внимание, что это вообще не поможет, если завершение всегда истинно асинхронно.
Дополнительные действия, которые применяются здесь:
1: с недавним C #, общий шаблон для async
метод резервного копирования обычно реализуется как локальная функция:
Task<string> DoTheThings() {
async Task<string> Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await a, await b, await c);
}
Task<Cat> x = FeedCat();
Task<House> y = FeedCat();
Task<Tesla> z = FeedCat();
if(x.Status == TaskStatus.RanToCompletion &&
y.Status == TaskStatus.RanToCompletion &&
z.Status == TaskStatus.RanToCompletion)
return Task.FromResult(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
2: предпочитает ValueTask<T>
- Task<T>
, если есть хорошие шансы на вещи когда-либо полностью синхронно со многими различными значениями возврата:
ValueTask<string> DoTheThings() {
async ValueTask<string> Awaited(ValueTask<Cat> a, Task<House> b, Task<Tesla> c) {
return DoWhatever(await a, await b, await c);
}
ValueTask<Cat> x = FeedCat();
ValueTask<House> y = FeedCat();
ValueTask<Tesla> z = FeedCat();
if(x.IsCompletedSuccessfully &&
y.IsCompletedSuccessfully &&
z.IsCompletedSuccessfully)
return new ValueTask<string>(
DoWhatever(a.Result, b.Result, c.Result));
// we can safely access .Result, as they are known
// to be ran-to-completion
return Awaited(x, y, z);
}
3: если возможно, предпочитайте IsCompletedSuccessfully
- Status == TaskStatus.RanToCompletion
; это теперь существует в .NET Core для Task
и везде для ValueTask<T>
Task
, когда все делается без использования результатов.
– Servy
6 February 2018 в 17:24
await
получить «лучше». исключая семантику, исходя из предположения, что исключения являются редкими, но значимыми
– Marc Gravell♦
6 February 2018 в 17:37
Вы можете сохранить их в задачах, а затем ждать их всех:
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
await Task.WhenAll(catTask, houseTask, carTask);
Cat cat = await catTask;
House house = await houseTask;
Car car = await carTask;
var catTask = FeedCat()
выполнение функции FeedCat()
и сохраняет результат в catTask
, делая часть await Task.WhenAll()
части бесполезной, поскольку метод уже выполнен?
– Kraang Prime
30 July 2016 в 23:09
Просто await
три задачи отдельно, после их запуска.
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
Task.WhenAll
практически ничего не меняет о поведении программы любым наблюдаемым способом. Это чисто избыточный вызов метода. Вы можете добавить его, если хотите, в качестве эстетического выбора, но это не меняет того, что делает код. Время выполнения кода будет идентичным с вызовом этого метода или без него (ну, технически будет накладные расходы действительно малые i> для вызова WhenAll
, но это должно быть незначительным), только делая это версии слегка i> дольше, чем эта версия.
– Servy
25 October 2017 в 21:22
Если вы пытаетесь зарегистрировать все ошибки, убедитесь, что вы сохранили строку Task.WhenAll в своем коде, многие комментарии предполагают, что вы можете удалить ее и дождаться отдельных задач. Task.WhenAll действительно важна для обработки ошибок. Без этой строки вы потенциально оставляете свой код открытым для незаметных исключений.
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
await Task.WhenAll(catTask, houseTask, carTask);
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
Представьте, что FeedCat генерирует исключение в следующем коде:
var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();
var cat = await catTask;
var house = await houseTask;
var car = await carTask;
В этом случае вы никогда не будете ждать houseTask или carTask. Существует 3 возможных сценария:
Вот ошибка, которую вы получите для случая (3):
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.HttpApplication.System.Web.Util.ISyncContext.Enter()
at System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action)
at System.Threading.Tasks.Task.Execute()
--- End of inner exception stack trace ---
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.HttpApplication.System.Web.Util.ISyncContext.Enter()
at System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action)
at System.Threading.Tasks.Task.Execute()<---
Для случая ( 2) вы получите аналогичную ошибку, но с исходной трассировкой стека исключений.
Для .NET 4.0 и более поздних версий вы можете поймать ненаблюдаемые исключения, используя TaskScheduler.UnobservedTaskException. Для .NET 4.5 и более поздних ненаблюдаемых исключений по умолчанию пропущено исключение unobserved .NET 4.0 приведет к сбою вашего процесса.
Подробнее здесь: Обработка исключений задач в .NET 4.5
Forward Warning
Просто быстрый хэдшоп для тех, кто посещает этот и другие подобные темы, ищет способ распараллеливать EntityFramework с помощью async + await + task tool-set: Образец, показанный здесь, звучит, однако, когда дело доходит до специальной снежинки EF, вы не достигнете параллельного выполнения, если только до тех пор, пока вы не будете использовать отдельный (новый) db-context-экземпляр внутри каждого вызова * Async ().
Этот вид что необходимо из-за присущих дизайну ограничений ef-db-контекстов, которые запрещают одновременное выполнение нескольких запросов в одном экземпляре ef-db-context.
Воспользовавшись уже предоставленными ответами, это это способ убедиться, что вы собираете все значения даже в том случае, если одна или несколько задач приводят к исключению:
var car = (Car) null;
var cat = (Cat) null;
var house = (House) null;
using (var carTask = BuyCarAsync())
using (var catTask = FeedCatAsync())
using (var houseTask = SellHouseAsync())
{
try {
await Task.WhenAll(carTask, catTask, houseTask);
} finally {
car = carTask.Status == TaskStatus.RanToCompletion ? await carTask : null;
cat = catTask.Status == TaskStatus.RanToCompletion ? await catTask : null;
house = houseTask.Status == TaskStatus.RanToCompletion ? await houseTask : null;
}
if (cat == null || car == null || house == null)
throw new SomethingFishyGoingOnHereException("...");
}
Совокупное исключение, которое содержит одно или несколько вспомогательных исключений, будет по-прежнему быть брошенным в конце.
Это зависит от вызывающей среды.
WhenAll
из этого полностью; ожидающие позаботятся о том, чтобы вы не проходили мимо 3 последующих заданий, пока все задачи не будут завершены. – Servy 19 June 2013 в 18:45Task.WhenAll()
позволяет запустить задачу в режиме parallel . Я не понимаю, почему @Servy предложил его удалить. БезWhenAll
они будут запускаться один за другим – Sergey 13 March 2015 в 13:07catTask
уже работает к моменту его возврата изFeedCat
. Таким образом, любой из подходов будет работать - единственный вопрос заключается в том, хотите ли выawait
по одному за раз или все вместе. Обработка ошибок несколько отличается - если вы используетеTask.WhenAll
, то всеawait
будут все, даже если один из них не работает раньше. – Stephen Cleary 13 March 2015 в 13:17WhenAll
не влияет на выполнение операций или их выполнение. Только i> имеет любую возможность i> влияния на результаты. В этом конкретном случае единственное различие заключается в том, что ошибка в одном из первых двух методов привела бы к тому, что исключение было бы выбрано в этом стеке вызовов ранее в моем методе, чем у Стивена (хотя такая же ошибка всегда была бы выбрана, если есть ). – Servy 16 March 2015 в 15:05