2017-02-14 7 views
0

Это то, что AsyncMethods класс выглядит следующим образом:методы Async, работающие на том же потоке, без временной задержки

public class AsyncMethods 
{ 
    public static async Task<double> GetdoubleAsync() 
    { 
     Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId); 
     await Task.Delay(1000); 
     return 80d; 
    } 
    public static async Task<string> GetStringAsync() 
    { 
     Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId); 
     await Task.Delay(1000); 
     return "async"; 
    } 
    public static async Task<DateTime> GetDateTimeAsync() 
    { 
     Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId); 
     await Task.Delay(1000); 
     return DateTime.Now; 
    } 
} 

Это то, что мой основной метод выглядит следующим образом:

static void Main(string[] args) 
{ 
    while (Console.ReadLine() != "exit") 
    { 
     Console.WriteLine("Thread.CurrentThread.ManagedThreadId: " + Thread.CurrentThread.ManagedThreadId); 
     DateTime dt = DateTime.Now; 
     var res = GetStuffAsync().Result; 
     var ts = DateTime.Now - dt; 
     Console.WriteLine(res); 
     Console.WriteLine("Seconds taken: " + ts.Seconds + " milliseconds taken: " + ts.Milliseconds); 
    } 
    Console.ReadLine(); 
    return; 
} 
static async Task<object> GetStuffAsync() 
{ 
    var doubleTask = AsyncMethods.GetdoubleAsync(); 
    var StringTask = AsyncMethods.GetStringAsync(); 
    var DateTimeTask = AsyncMethods.GetDateTimeAsync(); 

    return new 
    { 
     _double = await doubleTask, 
     _String = await StringTask, 
     _DateTime = await DateTimeTask, 
    }; 
} 

Как можно видеть, в каждом метод i добавил задержку в 1 секунду. Вот результат:

Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
{ _double = 80, _String = async, _DateTime = 2/15/2017 4:32:00 AM } 
Seconds taken: 1 milliseconds taken: 40 

Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
Thread.CurrentThread.ManagedThreadId: 10 
{ _double = 80, _String = async, _DateTime = 2/15/2017 4:32:03 AM } 
Seconds taken: 1 milliseconds taken: 16 

Теперь у меня есть 2 вопроса:

  1. Как приходят все произошло на одном потоке?
  2. Почему была задержка только 1 секунда, когда я ждал 3 секунды?
+0

Серьезно, VS не предупредил вас о синхронном вызове асинхронного кода? – stt106

+0

Если три задачи выполняются параллельно, и каждая задача имеет задержку в 1 секунду, то общая задержка составляет 1 секунду. Почему вы ожидали 3-секундной задержки? – juanreyesv

+0

@juanreyesv - Смотрите, как они все одинаковы. Как они работают параллельно в одном потоке? –

ответ

1

Все они начало на той же теме. Когда вы последовательно вызываете три метода Async, все они выполняются синхронно до первого вызова await. (После await они становятся государственными машинами, которые поднимаются там, где они останавливались, когда они планируют. Если вы проверили нить ID после, то вызов await Task.Delay, вероятно, вы найдете, что продолжения выполнялись на разных потоках - по крайней мере здесь в консольном приложении.)

Что касается того, почему это только задержка 1 секунда ... вот что вы говорите. У вас три задачи асинхронного программирования, все работают одновременно, каждый из которых задерживается на одну секунду. Вы не говорите: «[a] дождитесь завершения первой задачи до начала второго» - на самом деле вы делаете все наоборот, начиная все три, а затем ожидая всех трех, - поэтому они работают параллельно.

0

Ваш Console.WriteLine() вызывает в GetdoubleAsync(), GetStringAsync(), и GetDateTimeAsync() произошло в вызывающем потоке, потому что они оказались перед первым продолжением.

Ожидание вызова Task.Delay() возвращает поток обратно вызывающему коду.

Когда задача, возвращаемая Task.Delay() завершена, продолжение в этих задачах возвращает их значения и задает их задачи как завершенные.

Это позволило вашим 3 ожиданиям (в последовательном синхронном порядке) в GetStuffAsync() для возврата. Каждый из них должен был ждать 1 секунду, прежде чем был отмечен как завершенный, но они уступали и происходили в одно и то же время.

Я думаю, что вы ищете System.Threading.Tasks.Parallel, чтобы делать что-то в одно и то же время. Async ... await полезен для получения потоков.

12

Прежде всего: если у вас есть два вопроса: , пожалуйста, задайте два вопроса:. Не ставьте два вопроса в один вопрос.

Как все происходило на одном потоке?

Это неправильный вопрос. Правильный вопрос: почему вы думаете, что что-то должно произойти во втором потоке?

Здесь я дам вам задачу: подождите пять минут, а затем проверьте свою электронную почту.Пока вы ждете, сделайте бутерброд. Вам нужно было нанять кого-то, чтобы либо ждать, либо делать сэндвич? Очевидно нет. Темы - это рабочие. Нет необходимости нанимать работника, если работа может выполняться одним работником.

Целевая точка await: избегать, если вы не нуждаетесь в дополнительных потоках. В этом случае вам не нужно.

Почему была задержка только 1 секунда, когда я ждал 3 секунды?

Сравните эти два рабочих процесса.

  • Подождите пять минут; пока вы ждете, сделайте бутерброд
  • затем проверьте свой адрес электронной почты
  • затем подождите пять минут; пока вы ждете, сделайте бутерброд
  • затем проверьте свой адрес электронной почты
  • затем подождите пять минут; в то время как вы ждете, сделать бутерброд
  • затем проверить электронную почту

Если выполнить этот рабочий процесс, вы будете ждать в общей сложности пятнадцать минут.

Рабочий процесс Вы писали был:

  • Подождите пять минут
  • одновременно, подождите пять минут
  • одновременно, подождите пять минут
  • пока вы ждете, сделать бутерброд
  • затем проверьте ваш адрес электронной почты

You onl y ждать пять минут с этим документооборотом; все задержки происходят одновременно.

Вы видите, как вы писали свою программу неправильно сейчас?

Ключевое понимание, чтобы понять здесь, состоит в том, что Ожидание - это точка в программе, где продолжение ожидания задерживается до тех пор, пока ожидаемая задача не завершится.

Если вы не ожидаете, программа продолжит само по себе, не дожидаясь. В этом смысл await.

+0

Всегда «интересные» примеры в ваших ответах! – stt106

+0

@ Эрик Липперт: Весь смысл написания этой тестовой программы состоял в том, чтобы увидеть поведение async и threading. Вопрос, который до сих пор дергает мой мозг, - это то, как 1 + 1 + 1 секунда времени заполнить в одном потоке? Остальное, что вы сказали об асинхронности, заставило меня попробовать этот пример. Ответ Джо Уайта сделал для меня немного более ясным. –

+0

Ничего себе, удивительный ответ снова. Ваши аналогия с кодом лучше всего читаю. – VMAtm

0

Вы одновременно запускаете все свои задачи, чтобы все они запускались параллельно, а не последовательно. Вот почему все завершается через 1000 миллисекунд.

Кроме того, async не создает новые потоки, он использует текущую цепочку асинхронно. Такое поведение можно увидеть в async javascript (который представляет собой однопоточную среду) или сопрограммы в Unity3D. Они оба допускают асинхронное поведение без потоков.

Итак, каждая из ваших задач запускается в одном потоке и завершается через 1 секунду.

 Смежные вопросы

  • Нет связанных вопросов^_^