Я не вижу различий между новыми асинхронными функциями C # (и VB) и .NET 4.0 Task Parallel Library . Взять, к примеру, код Эрика Липперта отсюда :
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);
}
}
Кажется, что ключевое слово await
служит двум различным целям. Первое вхождение (FetchAsync
), по-видимому, означает: "Если это значение используется позже в методе и его задача не завершена, дождитесь его завершения, прежде чем продолжить." Второй экземпляр (archive
), по-видимому, означает: «Если это задание еще не выполнено, подождите прямо сейчас до его завершения». Если я ошибаюсь, исправьте меня .
Неужели так просто не написать так?
void ArchiveDocuments(List<Url> urls) {
for(int i = 0; i < urls.Count; ++i) {
var document = FetchAsync(urls[i]); // removed await
if (archive != null)
archive.Wait(); // changed to .Wait()
archive = ArchiveAsync(document.Result); // added .Result
}
}
Я заменил первый await
на Task.Result
, где значение действительно требуется, а второй await
на Task.Wait()
, где фактически происходит ожидание. Функциональность (1)
уже реализована, и (2)
семантически намного ближе к тому, что фактически происходит в коде.
Я понимаю, что метод async
переписан как конечный автомат, похожий на итераторы, но я также не вижу, какие преимущества это дает. Любой код, для работы которого требуется другой поток (например, загрузка), по-прежнему будет нуждаться в другом потоке, и любой код, который этого не делает (например, чтение из файла), может по-прежнему использовать TPL для работы только с одним потоком.
Я явно упускаю что-то огромное здесь; Кто-нибудь может помочь мне понять это немного лучше?