https://msdn.microsoft.com/ru-ru/library/hh156528.aspxВыражение await не блокирует поток, в котором оно выполняется. Вместо этого оно указывает компилятору объявить оставшуюся часть асинхронного метода как продолжение ожидаемой задачи. Управление затем возвращается методу, вызвавшему асинхронный метод. Когда задача завершается, она вызывает свое продолжение и возобновляет выполнение асинхронного метода с того места, где она была прервана.
Метод
Task.Run ставит в очередь заданную задачу для запуска в пуле потоков.
Т.е. в первом случае, у вас просто будет добавлена задача в очередь на выполнение и продолжено выполнение программы (без ожидания, программа может завершить работу раньше, чем созданная задача). А во втором, текущий поток будет ожидать завершения выполнения асинхронной операции. Основной поток при использовании
await заморожен не будет.
// без ожидания
Console.WriteLine(DateTime.Now);
Task.Run(() => { Thread.Sleep(5000); });
// этот код будет выполнен сразу
Console.WriteLine(DateTime.Now);
// ожидание с await
Console.WriteLine(DateTime.Now);
await Task.Run(() => { Thread.Sleep(5000); });
// этот код будет выполнен, только после завершения выполнения задачи
// текущий (вызывающий) поток не будет приостановлен
// (например, в Windows Form это будет хорошо видно)
Console.WriteLine(DateTime.Now);
Если сделать задачу и вызвать метод
Wait, то основной поток будет приостановлен, пока не завершится задача.
Console.WriteLine(DateTime.Now);
var t = Task.Run(() => { Thread.Sleep(5000); });
t.Wait(); // ожидание выполнения задачи
// этот код будет выполнен, только после завершения выполнения задачи
// текущий (вызывающий) поток будет блокирован
// (например, в Windows Form это будет хорошо видно)
Console.WriteLine(DateTime.Now);