Что может вызвать синхронный запуск метода, помеченного async, даже если он содержит вызов await? - PullRequest
2 голосов
/ 06 января 2012

Я пытаюсь отладить код, который написал мой коллега, пока его нет.

Вот звонок:

var sw = Stopwatch.StartNew();
logger.Trace("Time A: {0}ms", sw.ElapsedMilliseconds); // Roughly 0ms
pt.Task = ProcessMetricsWorker(pt.CancelTokenSource);
sw.Stop();
logger.Trace("Time B: {0}ms", sw.ElapsedMilliseconds); // Over 20000ms!

Вот подпись метода:

async Task ProcessMetricsWorker(CancellationTokenSource cancelTokenSource)

Этот метод занимает около 20 секунд для запуска, и в соответствии с регистрацией, которую я помещаю непосредственно перед и после первой строки, указанной выше, задача выполняется синхронно, как если бы часть async игнорировалась. Что могло бы вызвать это?

Обратите внимание, что внутри асинхронного метода есть вызов await. Это внутри цикла, хотя я не могу себе представить, что это изменит ситуацию.

// internal to the method referenced above
result = await metricProcessor.ProcessItem(domain);

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

Ответы [ 2 ]

4 голосов
/ 06 января 2012

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

Итак, есть пара возможностей того, что происходитв ProcessMetricsWorker:

  • Может содержать некоторый длительный синхронный код перед первым await.
  • Многие из первых ожидают, что await s уже могут бытьзавершено.Если они все уже завершены, то ProcessMetricsWorker фактически является синхронным.

«Быстрый путь» сообщение в блоге содержит более подробную информацию о том, как await преобразуется в код и показывает, как оно дает только если оно действует на незавершенное ожидание.

0 голосов
/ 06 января 2012

Ну, я думаю, что нашел ошибку в Async CTP.

Я добавил этот метод:

async Task DummyTask()
{
    await TaskEx.Run(() => Thread.Sleep(1000));
}

Затем добавил прямо в метод ProcessMetricsWorker:

await DummyTask();

Привет, метод теперь асинхронный!Мне интересно, если компилятор как-то проигнорировал внутренний вызов await в методе, и все это вышло синхронно в коде MSIL ...

...