В С # 5.0 функция async / await всегда выполняется в основном потоке в начале выполнения

Я обнаружил, что когда я вызываю «асинхронную» функцию, сначала поток является основным потоком. Когда он встречает задачу ожидания, поток будет изменен на другой.

static void Main(string[] args)
{
    println("Mainthread ID " + Thread.CurrentThread.GetHashCode());
    var s = DoSomethingAsync();
    println("Waiting for DoSomethingAsync Complete ");
    Thread.Sleep(2000);
    println(s.Result.ToString());
}

static async Task<int> DoSomethingAsync()
{
    println("DoSomethingAsync Thread ID " + Thread.CurrentThread.GetHashCode());
    int val = await Task.Factory.StartNew(() =>
    {
        Thread.Sleep(1000);
        println("Task Thread ID " + Thread.CurrentThread.GetHashCode());
        return 100;
    });

    println("DoSomethingAsync end " + Thread.CurrentThread.GetHashCode());
    return val;

}

Результат следующий:

11:40:34 383 Mainthread ID 1
11:40:34 398 DoSomethingAsync Thread ID 1
11:40:34 400 Waiting for DoSomethingAsync Complete
11:40:35 400 Task Thread ID 3
11:40:35 400 DoSomethingAsync end 3
11:40:36 401 100

Мы видим, что идентификатор основного потока равен 1. Идентификатор потока DoSomethingAsync также равен 1. Они такие же. Итак, в начале выполнения функции «async» эту часть выполняет основной поток.

Это означает, что когда основной поток встречает функцию «async», он будет заблокирован для выполнения чего-либо до тех пор, пока не встретит задачу await. Функция «async» не делает вещи асинхронными мгновенно. Это правильно?

Я знаю, что если в функции «async» нет задачи ожидания, эта функция «async» будет выполняться синхронно.


person roast_soul    schedule 12.08.2014    source источник


Ответы (2)


Это означает, что когда основной поток встречает функцию «async», он будет заблокирован для выполнения чего-либо до тех пор, пока не встретит задачу await. Функция «async» не делает вещи асинхронными мгновенно. Это правильно?

Да, именно так. Ваш async метод будет работать до тех пор, пока не будет достигнуто первое await ключевое слово, после чего управление будет возвращено вызывающей стороне. В вашем примере вы не используете await этот метод, поэтому он сразу же продолжит выполнение следующего метода.

Кстати, консольное приложение на самом деле не имеет Main Thread, поскольку оно использует значение по умолчанию ThreadPoolSynchronizationContext. Это означает, что вы увидите любой произвольный идентификатор потока после ожидаемого асинхронного метода.

person Yuval Itzchakov    schedule 12.08.2014

Метод начнет работать в любом потоке, вызывающем метод. Если метод вызывается из основного потока, он запускается в основном потоке. Если он вызывается из потока пула потоков, он начинает работать в потоке пула потоков. В этом отношении он ничем не отличается от любого другого метода.

Продолжение после любой await операции будет использовать текущую SyncrhonizationContext, чтобы определить, как они запланированы.

person Servy    schedule 12.08.2014