Теперь, когда мы знаем, что ожидает c # 5, нам, видимо, еще есть возможность повлиять на выбор двух новых ключевых слов для « асинхронности », которые были анонсированы Андерсом Хейсбергом вчера на PDC10 .
async void ArchiveDocuments(List<Url> urls) {
Task archive = null;
for(int i = 0; i < urls.Count; ++i) {
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
У Эрика Липперта есть объяснение выбора двух текущих ключевых слов и того, как их неправильно поняли в исследованиях юзабилити. В комментариях есть несколько других предложений.
Пожалуйста - одно предложение за ответ, дубликаты будут уничтожены.
Ответы:
Учитывая, что я не совсем понимаю значение / необходимость
async
, я не могу спорить с этим, но мое лучшее предложение для заменыawait
:yield while
(смотрите! нет новых ключевых слов)Обратите внимание , подумав об этом немного больше, я задаюсь вопросом, является ли повторное использование
while
таким способом хорошей идеей - естественной тенденцией будет ожидание логического значения после этого.(Думает: поиск хороших ключевых слов - это как поиск хороших доменных имен :)
источник
while(x) {...}
, еслиx
false.while
. Если вы добавляете глагол, напримерdo
, вы получаетеdo {...} while (x)
, который выполняет тело независимо от x (хотя бы один раз). Ваше предположениеyield while
кажется очень похожимdo while
, но с противоположными гарантиями выполнения глагола, что может быть немного вводящим в заблуждение (но не так уж и важно). Больше всего мне не нравится тоyield
, что это подразумевает реализацию механизма. Весь смыслasync
/ вawait
том, что вы пишете асинхронную операцию в синхронном стиле.yield
нарушает этот синхронный стиль.await
ключевое слово будет распознаваться контекстом, поэтому вы все равно можете иметь метод или переменную с именем «await», если хотите. В некоторой степени, я думаю, что использование нового ключевого слова для новой функциональности менее запутанно, чем повторное использование существующего ключевого слова для обозначения нескольких вещей. (преувеличенный пример: dangermouse.net/esoteric/ook.html )Как насчет отсутствия ключевого слова?
Я бы хотел, чтобы компилятор понял, что большую часть времени, когда я вызываю асинхронный метод, я хочу получить его результат.
Вот и все. Причина, по которой людям трудно придумать ключевое слово для этой вещи, заключается в том, что это все равно, что иметь ключевое слово для «делай то, что сделал бы, если бы все было совершенно нормально». Это должно быть по умолчанию, а не требовать ключевое слово.
Обновить
Первоначально я предложил компилятору разобраться с выводом типа, чтобы понять, что делать. Подумав об этом дальше, я бы сохранил существующую реализацию в CTP как есть, но сделаю пару тривиальных дополнений к ней, чтобы уменьшить случаи, когда вам нужно будет использовать
await
явно ключевое слово.Мы изобретаем атрибут:
[AutoAwait]
. Это может быть применено только к методам. Один из способов применить это к вашему методу - пометить егоasync
. Но вы также можете сделать это вручную, например:Затем внутри любого
async
метода компилятор будет предполагать, что вы хотите ожидать вызоваDownloadDocumentAsync
, поэтому вам не нужно его указывать. Любой вызов этого метода будет автоматически ожидать его.Теперь, если вы хотите «стать умным» и получить
Task<Document>
, вы используете операторstart
, который может появиться только перед вызовом метода:Я думаю, аккуратно. Теперь простой вызов метода означает то, что он обычно означает: дождитесь завершения метода. И
start
указывает на что-то другое: не ждите.Для кода, который появляется за пределами
async
метода, единственный способ, которым вы можете вызывать[AutoAwait]
метод - это префикс егоstart
. Это заставляет вас писать код, имеющий одинаковое значение, независимо от того, появляется он вasync
методе или нет.Тогда я начинаю жадничать! :)
Во-первых, я хочу
async
применить методы интерфейса:В основном это означает, что метод реализации должен возвращать
Task<int>
или что-то совместимое сawait
, и вызывающие методы получат[AutoAwait]
поведение.Также, когда я реализую описанный выше метод, я хочу иметь возможность написать:
Так что я не должен упоминать
Task<int>
в качестве типа возврата.Кроме того, я хочу
async
применить к типам делегатов (которые, в конце концов, похожи на интерфейсы с одним методом). Так:async
Делегат имеет - вы уже догадались -[AutoAwait]
поведение. Изasync
метода вы можете вызывать его, и он будет автоматическиawait
редактироваться (если вы не решите простоstart
его). И так, если вы скажете:Это просто работает. Это не вызов метода. Ни одна задача еще не была запущена - это
async delegate
не задача. Это фабрика для постановки задач. Ты можешь сказать:И это запустит задачу и будет ждать ее завершения и даст вам результат. Или вы можете сказать:
Таким образом, единственное место в этом, где просачивается «сантехника», это то, что если вы хотите создать делегат для
async
метода, вы должны знать, чтобы использоватьasync delegate
тип. Так что вместоFunc
тебя надо сказатьAsyncFunc
и так далее. Хотя однажды такие вещи можно исправить с помощью улучшенного вывода типа.Другой вопрос, что должно произойти, если вы скажете начать с обычного (не асинхронного) метода. Очевидно, что ошибка компиляции будет безопасным вариантом. Но есть и другие возможности.
источник
var
, возможно, необходимости заменить какое-то длинное явное имя типа, а также неоднозначно междуawait
случаем и случаем, когда кто-то случайно вызвал асинхронный метод вместо обычного синхронного метода. Сначала это кажется интуитивно понятным, но на самом деле нарушает принцип наименьшего удивления.var
? Интересно, отвечаете ли вы на предыдущую редакцию моего ответа ... Я полностью переписал его. Теперь вы можете думать об этом предложении следующим образом: если метод помечен специальным атрибутом, это как если быawait
ключевое слово автоматически вставлялось перед вызовами этого метода (если вы не подавите это с помощьюstart
префикса). Все остается точно так же, как в CTP, и, следовательно,var
работает нормально.public async Task<int> FooAsync()
.(если вы не получите его, прочитайте запись Эрика в блоге . По крайней мере, это лучше, чем
for sooth Romeo wherefore art thou AsyncFetch(…)
)источник
Я думаю, что
async
это хорошо, но, возможно, это потому, что я связываю это с асинхронными страницами ASP.NET - та же идея.Для
await
ключевого слова я предпочитаюcontinue after
илиresume after
.Мне не нравится
yield
ни один из его вариантов, потому что семантика такова, что метод может никогда не привести к выполнению; это зависит от состояния задачи.источник
resume after
заawait
. Можетasync
быть, можно назватьresumable
.after
, уcontinue after
подхода есть сильное преимущество реализации: он включает в себя существующее в настоящее время контекстное ключевое слово, но с синтаксисом, который не совместим с текущим использованием. Это гарантирует, что дополнение никогда не нарушит существующий код. При использовании совершенно нового ключевого слова реализация должна справляться с возможным использованием слова в качестве идентификатора в более старом коде, что может быть довольно сложно.Я добавил к комментариям в блоге Эрика тоже, я не вижу проблем с использованием того же ключевого слова
async
Я просто заявляю, что хочу загрузить файл асинхронно. Здесь есть небольшая избыточность, «асинхронность» появляется дважды, потому что она тоже есть в имени метода. Компилятор может быть очень умным и обнаружить соглашение о том, что методы, оканчивающиеся на «Async», являются фактически асинхронными методами, и добавить это для нас в скомпилированном коде. Так что вместо этого вы можете просто позвонить
в отличие от вызова синхронного
Черт возьми, мы также должны иметь возможность определять их одинаково, поскольку в нашем объявлении есть ключевое слово async, почему мы должны вручную добавлять «Async» к каждому имени метода - компилятор может сделать это за нас.
источник
async
ключевое слово в методе - просто изящность (если я правильно понял), я задаюсь вопросом, не лучше ли было бы сделать противоположность тому, что вы предлагаете: отказатьсяasync
от метода on и просто использовать его где они сейчас естьawait
.async Task<Byte[]> DownloadFile(...)
а неTask<Byte[]> DownloadFileAsync(...)
(последняя будет скомпилированной подписью в любом случае). В любом случае работает.async = task - это изменение функции для возврата задачи, так почему бы не использовать ключевое слово "task"?
await = finish - нам не обязательно ждать, но задача должна "закончиться", прежде чем использовать результат.
источник
Мне нравится
yield until
.yield while
Как уже говорилось, это здорово, и не вводит никаких новых ключевых слов, но я думаю, что «пока» не поймет поведение немного лучше.Я думаю, что
yield <something>
это отличная идея, потому что yield уже отражает идею превращения оставшейся части метода в продолжение. Может быть, кто-то может придумать лучшее слово, чем «до».источник
Я просто хочу зарегистрировать свой голос за предложение Аарона Дж
comefrom
- первое соответствующее использование заявления COMEFROM от INTERCAL . Идея состоит в том, что это своего рода противоположность GOTO (отходит от оператора GOTO) в том, что в вашем коде происходит переход к команде COMEFROM.источник
Поскольку мы имеем дело с
Task<T>
s, как насчет использованияstart
в качестве ключевого слова перед оператором, как в:start var document = FetchAsync(urls[i]);
источник
finish
быть, даже лучше, чемstart
?Стоит отметить, что F # также использует
async
ключевое слово в своих асинхронных рабочих процессах, что в значительной степени совпадает с новой функциональностью асинхронности в C # 5. Поэтому я бы сохранил этоДля
await
ключевого слова в F # они просто используютlet!
вместоlet
. C # не имеет такой же синтаксис присваивания, поэтому им нужно что-то справа от=
знака. Как сказал Бенджол, он функционирует так же, какyield
и должен быть почти таким вариантом.источник
do!
, но ты знал это ...yield async FetchAsync(..)
Это прекрасно сочетается с
async
модификатором, который вам нужен для метода, который вы вызываете. А также семантика текущего,yield return
то есть вы возвращаете выполнение и передаете его перечисляющему коду, в этом случае вы уступаете свое выполнение асинхронному методу.Представьте, что в будущем появятся другие варианты использования
yield
, мы могли бы добавить,yield x
где x - это блестящая новая функция вместо того, чтобы все эти разные ключевые слова выполняли в основном одно и то же, принося результат.Честно говоря, я не совсем понимаю аргумент «не поддающийся казни». В конце концов, разве смысл в том, чтобы вызывать другой метод, уже заключается в том, чтобы «дать выполнение» этому методу? Независимо от того, является ли он асинхронным или нет? Я что-то здесь упускаю?
И хорошо, если
async
возврат выполняется синхронно, но наличие ключевого слова должно означать, что есть вероятность того, что метод будет работать асинхронно и что вы уступите выполнение другому методу. Ваш метод должен учитывать это независимо от того, выполняет ли метод асинхронные вызовы или нет.ИМО Я думаю, что различные «не приносящие» случаи являются деталями реализации. Я предпочел бы ручаться за последовательность в языке (то есть повторное использование
yield
).источник
Как насчет того
complete
, как в «Я хочу, чтобы задача была выполнена»?источник
task
(для объявления метода) иasync
(в теле метода)источник