Нет, вы указали причину, по которой это уже отличается. Parallel и Async - это разные вещи.
Версия Task работает за 2 секунды, потому что она выполняет три операции одновременно (при условии, что у вас есть 3+ процессора).
На самом деле ожидание - это то, на что это похоже, код будет ожидать выполнения Task.Run, прежде чем перейти к следующей строке кода.
Итак, большая разница между версией TPL и асинхронной версией заключается в том, что версия TPL выполняется в любом порядке, поскольку все задачи не зависят друг от друга. Принимая во внимание, что асинхронная версия выполняется в порядке написания кода. Так что, если вы хотите параллельный, используйте TPL, а если вы хотите асинхронный, используйте async.
Смысл асинхронности - возможность писать синхронно выглядящий код, который не будет блокировать пользовательский интерфейс во время продолжительного действия. Тем не менее, это обычно действие, которое все, что делает процессор, ожидает ответа. Функция async / await делает так, чтобы код, вызвавший метод async, не ожидал возврата метода async, вот и все. Итак, если вы действительно хотите эмулировать свою первую модель, используя async / await (что я бы НЕ предложил), вы можете сделать что-то вроде этого:
MainMethod()
{
RunTask1();
RunTask2();
RunTask3();
}
async RunTask1()
{
var one = await Task.Factory.StartNew(()=>TestOutput.DoWork("one"));
//do stuff with one
}
async RunTask2()
{
var two= await Task.Factory.StartNew(()=>TestOutput.DoWork("two"));
//do stuff with two
}
async RunTask3()
{
var three= await Task.Factory.StartNew(()=>TestOutput.DoWork("three"));
//do stuff with three
}
Путь кода будет выглядеть примерно так (если задачи долго выполняются)
- основной вызов RunTask1
- RunTask1 ждет и возвращает
- основной вызов RunTask2
- RunTask2 ждет и возвращает
- основной вызов RunTask3
- RunTask3 ждет и возвращает
- Основное теперь сделано
- RunTask1 / 2/3 возвращается и продолжает что-то делать с одним / двумя / тремя
- То же, что 7, за исключением того, что уже завершено
- То же, что 7, за исключением двух уже законченных
**** Хотя это и большой отказ от ответственности. Ожидание будет выполняться синхронно, если задача уже завершена к тому моменту, когда ожидается ожидание. Это избавляет среду выполнения от необходимости выполнять ее вуду :), так как она не нужна. Это сделает поток кода выше неправильным, поскольку поток теперь синхронный ****
В блоге Эрика Липперта об этом все объясняется гораздо лучше, чем я делаю :)
http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx
Надеюсь, это поможет развеять некоторые ваши вопросы об асинхронности по сравнению с TPL? Самое главное, что нужно убрать, это то, что асинхронность НЕ параллельна.