Хорошо, два случая var tasks = docs.Select(d => d.AnyTask()).ToArray();
docs.ForEach(async d => await d.AnyTask());
В первом случае хочу просто собрать таски и выполнить их потом. Во втором хочу начать выполнять немедленно. Как мне различить эти ситуации? В первом случае таски начнут выполняться сейчас же?
В моём случае с Load я не могу убрать await, поскольку метод возвращает таск, который мне нужно запустить. Если бы это был асинхронный воид метод, то тогда да, можно было бы написать так
Ваши претензии насчёт «читаемости» кода лучше адресовать к архитекторам C#, которые ввели именно такую реализацию async...await с немалым количеством подводных камней.
Что касается написанного именно мной кода, то он весьма тривиален — это всего лишь цепочные вариации метода ForEach очень схожие с одноименным методом у класса List. То есть запросто без всяких дополнительных расширений сейчас можно писать такой код
new List<ADocument>() {...}
.ForEach(async d => await d.DoSomething());
Насколько понимаю, вы хотите сказать, что интуитивное добавление async...await ломает его читабельность?
Да, я ошибся с тем, что он должен выполняться параллельно, но при искуственном добавлении задержки в метод Load ничего в моей программе не сломалось и не заблокировалось, просто текст из файла загрузился чуть позже, из чего делаю вывод, что интуиция меня не подвела и работает код, по крайней мере, асинхронно, как и хотелось.
В конкретном случае главной вью-модели вообще не важен результат загрузки. Но, например, важен результат закрытия: в самом конеце файла, 81 строка, метод Close.
Благодарю за бенчмарки. Примерно таких результатов я и ожидал — всё в допустимых пределах, различия нет даже в десять раз. Одна и пять миллионных секунды — в подавляющем большинстве практических случаев неразличимы.
По fallbackValue, методу нужен булевый признак и он работает с value types, которые оператор 'as' не поддерживает.
Потому что нет лишних ресурсов.
Много же нужно ресурсов, чтобы вместо выражения object.Equals(...) подставить
EqualityComparer<T>.Default.Equals(...)
«Интересные вещи» — совсем не то же самое, что «обобщение».
Рассматриваемые интересные вещи уже довольно-таки обобщены на широкий круг сценариев.
Когда вы впервые видите какой-то метод, то зачастую не знаете деталей его имплементации — это нормально, вы просто смотрите код или читаете описание в документации.
public static IList<T> ForEach<T, TR>(
this IList<T> collection,
Func<T, TR> action)
{
foreach (var item in collection)
action(item);
return collection;
}
После этого многие вопросы пропадают, и вас уже не смущает этот же вызов в другом месте программы.
Ну так не читайте и не понимайте, никто здесь вас не принуждает чего-то делать. )
Просто ваша призыв выглядит сейчас так: «Не учите интегралы, они трудные, с ними легко ошибиться, и они, наверняка, не пригодятся вам в жизни. Пользуйтесь школьной математикой, она простая, понятная, хорошо применима на практике, и многие ей хорошо владеют».
Вся логика работы с файлом (или группой фалов) инкапсулирована внутри самого документа.
Основной вью-модели или кому-то ещё вообще не нужно знать, как конкретно документ работает с файлами или даже какими-то другими ресурсами, а уж тем более какие ошибки могут при этом возникнуть и как их обрабатывать.
var tasks = docs.Select(d => d.AnyTask()).ToArray();docs.ForEach(async d => await d.AnyTask());
В первом случае хочу просто собрать таски и выполнить их потом. Во втором хочу начать выполнять немедленно. Как мне различить эти ситуации? В первом случае таски начнут выполняться сейчас же?
Насколько понимаю, если вместо StartNew буду использовать ReadToEndAsync, то тогда await убрать не смогу, верно? Или интуиция опять подводит?
async void Load() => await ......ForEach(d => d.Load());
async () => await SomeAsync()запускает таск, а вот() => SomeAsync()просто его возвращает, не запуская.Task task...
() => task = SomeAsync()
И как вообще я могу убрать await в таком случае?
Тасками я пользуюсь по большей части интуитивно и стараюсь избегать дебрей с контекстами синхронизации.
Ваши претензии насчёт «читаемости» кода лучше адресовать к архитекторам C#, которые ввели именно такую реализацию async...await с немалым количеством подводных камней.
Что касается написанного именно мной кода, то он весьма тривиален — это всего лишь цепочные вариации метода ForEach очень схожие с одноименным методом у класса List. То есть запросто без всяких дополнительных расширений сейчас можно писать такой код
Насколько понимаю, вы хотите сказать, что интуитивное добавление async...await ломает его читабельность?
Да, я ошибся с тем, что он должен выполняться параллельно, но при искуственном добавлении задержки в метод Load ничего в моей программе не сломалось и не заблокировалось, просто текст из файла загрузился чуть позже, из чего делаю вывод, что интуиция меня не подвела и работает код, по крайней мере, асинхронно, как и хотелось.
По fallbackValue, методу нужен булевый признак и он работает с value types, которые оператор 'as' не поддерживает.
Много же нужно ресурсов, чтобы вместо выражения
object.Equals(...)подставитьРассматриваемые интересные вещи уже довольно-таки обобщены на широкий круг сценариев.
После этого многие вопросы пропадают, и вас уже не смущает этот же вызов в другом месте программы.
Просто ваша призыв выглядит сейчас так: «Не учите интегралы, они трудные, с ними легко ошибиться, и они, наверняка, не пригодятся вам в жизни. Пользуйтесь школьной математикой, она простая, понятная, хорошо применима на практике, и многие ей хорошо владеют».
Вся логика работы с файлом (или группой фалов) инкапсулирована внутри самого документа.
Основной вью-модели или кому-то ещё вообще не нужно знать, как конкретно документ работает с файлами или даже какими-то другими ресурсами, а уж тем более какие ошибки могут при этом возникнуть и как их обрабатывать.
1. Подготовили докуметы к работе
2. Асинхронно вызвали параллельную загрузку данных в каждый
Всё. Документы уже готовы к работе и сами разберутся, что делать при возникновении ошибок.