Подтвердить что ты не робот

Насколько отличается ожидание/асинхронный поток от потоковой передачи?

Я пытаюсь познакомиться с ключевыми словами cue new/ожидания async, и я нашел несколько аспектов, которые я не могу понять.

  • Начните с условий гонки:

    Stream s=...
    ...
    for(int i=0;i<100;i++)
    {
        s.WriteAsync(new byte[]{i},0,1);
    }
    

    будет работать так, как ожидалось, все время (например, писать в файл 12345..... а не 13254 или что-то в этом роде)?

    Во-вторых, функция async выполняется синхронно, если она не содержит оператора ожидания. И, согласно документации Microsoft, функции async всегда выполняются в потоке вызывающего (по сравнению с BeginInvoke). Это приводит меня к трем следующим вопросам:

  • Сколько из функции async выполняется до того, как оно будет выпущено в функцию вызывающего абонента?

    async void MyAsyncFunction()
    {
        Operation1();
        Operation2();
        Operation3();
        ....
        Stream s=...;
        await s.WriteAsync(....);
    }
    

    В статьях о await/async, которые я прочитал, он сказал, что асинхронные функции без ожидания выполняются последовательно, а с ожиданием async/await. Но он ворчит в меня, что MyAsyncFunction всегда может выполнять Operation1... Operation3 перед выпуском, когда он достигает await s.WriteAsync.

  • Что делать, если я использую Thread.Sleep в async-функции, например:

    async void DoStuff()
    {
        Stream s=...;
        ...
        await s.WriteAsync(....);
        Thread.Sleep(10000);
        ....
    }
    

    Будет ли Thread.Sleep блокировать весь поток, в котором он выполняется, или просто функция async?

  • Что делать, если я использую semaphore.Wait() в одной из функций async, и ожидается, что семафор будет выпущен другой функцией async. Будет ли это вести себя так же, как с потоками, или это вызовет тупик?

  • await не работает вне функций async. Почему?

4b9b3361

Ответ 1

Я рекомендую вам прочитать мой async intro.

будет работать все время (например, писать в файл 12345..... а не 13254 или что-то еще)?

Нет. Вы должны await вызвать WriteAsync.

Сколько из функции async выполняется до того, как оно будет выпущено для функции звонящего?

До тех пор, пока не будет await операция, которая еще не завершена.

Будет ли Thread.Sleep блокировать весь поток, в котором он выполняется, или просто функция async?

Thread.Sleep - и все другие методы блокировки - заблокируют метод async и поток, выполняющий его.

Как правило, не используйте какие-либо методы блокировки в методе async.

Что делать, если я использую функцию semaphore.Wait() в одной из асинхронных функций, и ожидается, что семафор будет выпущен другой функцией async. Будет ли это вести себя так же, как с потоками, или это вызовет тупик?

Это полностью зависит от ваших контекстов. Wait - это метод блокировки, поэтому, если для "другого" async метода требуется контекст, удерживаемый блокированным методом, тогда вы закроетесь.

Обратите внимание, что SemaphoreSlim async - дружелюбно; вы можете использовать WaitAsync вместо Wait.

Ожидание не работает вне функций async. Почему?

Поскольку ключевое слово async включает ключевое слово await. Это было сделано для минимизации влияния новых ключевых слов на язык С# и на удобочитаемость кода.

Ответ 2

Вы можете найти ответ на свои вопросы об операторе await в следующем сообщении от Eric Lippert, где он говорит, что:

Оператор "ожидание"... не означает, что теперь этот метод блокирует текущий поток до тех пор, пока асинхронная операция не вернется ". сделать асинхронную операцию обратно синхронной и это именно то, чего мы пытаемся избежать. Скорее, это означает противоположность этому; это означает" если задача, которую мы ожидаем еще не завершил, тогда зарегистрируйте остальную часть этого метода как продолжение этой задачи, а затем немедленно вернуться к вызывающему абоненту; задача будет вызывать продолжение при завершении. - Эрик Липперт

Ответ 3

Короче говоря, кажется, что ответ "очень". Хотя следующие вопросы могут не отвечать на все ваши вопросы, я думаю, что это относится к достаточно большому варианту использования. Подумайте о своем потоке вместо сетевого ввода-вывода, на который они ссылаются.

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

Это означает, что, пока мы "ждем" завершения, поток не будет потребляться. [...]

Можно делать все на 1 потоке. [...] Однако он будет зависеть от платформы, реализации "awaiter" и используемого контекста синхронизации.

http://social.msdn.microsoft.com/Forums/en-US/async/thread/a46c8a54-f8d4-4fa9-8746-64d6a3a7540d/