2015-10-01 2 views
1

Если метод отмечен как асинхронный, то он поставляется с любыми гарантиями?Что такое асинхронная гарантия?

Если нет, то каковы наилучшие методы для вызова методов асинхронизации для обеспечения неблокирующего поведения? (Особенно при вызове библиотеки сторонних производителей)


Longer версия:

До сих пор, я предположил, что ожидает метод асинхронной гарантированно не блокировать поток (если все сделано правильно). Тем не менее, у меня недавно было this situation (также случилось с others). В этом случае поведение (не) блокировки зависит от поставщика EF. Поскольку уровень пользовательского интерфейса не должен действительно знать или заботиться о деталях реализации поставщика БД, я полагаю, что имеет смысл обернуть все вызовы в Task.Run, чтобы обеспечить неблокирующее bahaviour. Но тогда мне не нужна асинхронная нигде, кроме слоя пользовательского интерфейса, что заставляет меня подвергать сомнению философию полного асинхронизации.

+0

вы должны «ожидать» вызов метода асинхронного доступа iirc –

+0

Для этого требуется небольшая работа, но одна вещь, которую он * не гарантирует, и это то, что вы не получите побочные эффекты любого кода, который вы вызовите или вне методов async. – Will

+0

[Здесь] (https://docs.com/paulo-morgado/8860/async-await-general "async-wait general") представляет собой набор статей на 'async'-'await'. –

ответ

4

Опознавание метода async на самом деле не имеет никаких гарантий и, конечно же, не гарантирует, что метод будет выполняться асинхронно.

Что это сделать (но я бы не назвал эти гарантии):

  • Включает использование await ключевого слова внутри метода (но делает не применять его!).
  • Это заставляет возвратный тип метода быть void, Task или Task<TResult>. И в последних двух случаях он позволяет компилятору генерировать код для вас, который знает, как установить возвращаемое значение в Task, или что касается прозрачного распространения необработанных исключений.

Но для выразительности: это делает не гарантию того, что этот метод будет кодироваться в асинхронном режиме. И вы можете проверить это сами. Напишите обычный метод, отметьте его как async и «забудьте» await что-нибудь внутри метода. Вы должны получить предупреждение от компилятора о синхронном методе, но это будет разрешено.

Я думаю, что вы найдете его полезным, чтобы пройти через Async/Await FAQ, чтобы прояснить некоторые из ваших сомнений:

ли с помощью ключевого слова async по методу силы все вызовы этого метода асинхронным?

№ При вызове метода, отмеченного как async, он начинает работать синхронно по текущему потоку. Итак, если у вас есть синхронный метод, который возвращает void, и все, что вы делаете, чтобы изменить его, отметьте его как async, вызовы этого метода все равно будут выполняться синхронно. Это верно независимо от того, оставите ли вы возвращаемый тип как void или измените его на Task. Аналогично, если у вас есть синхронный метод, который возвращает некоторый TResult, и все, что вы делаете, отметьте его как async и измените тип возвращаемого значения на Task<TResult>, а вызовы этого метода будут выполняться синхронно.

Маркировка метода как «асинхронная» не влияет на то, выполняется ли метод до завершения синхронно или асинхронно.

+0

Так что в основном я всегда должен обернуть вызов в Task.Run, если я хочу быть абсолютно уверенным, что он будет запускаться асинхронно, а не блокировать где-то глубоко. И если я это сделаю, нет никакой пользы от асинхронного использования, кроме как в вызывающей части. – loodakrawa

+1

", конечно, не гарантирует, что метод будет работать синхронно." Вы имели в виду * асинхронно *? – svick

+0

@svick: oops, typo. Спасибо. – sstan

2

Я предполагаю, что это имеет смысл, чтобы обернуть все вызовы в Task.Run для обеспечения неблокирующая bahaviour

Я не думаю, что это делает. Хотя у вас действительно нет гарантий, самыеasync методы будут фактически асинхронными. Поэтому я думаю, что вы должны обернуть вызовы в Task.Run() только после того, как выяснишь, что метод (или его реализация) фактически блокирует, но не раньше.

1

Если метод помечен как async, имеет ли он какие-либо гарантии?

Нет, как утверждают другие, он не гарантирует, что фактическая операция является асинхронной. Это всего лишь намек на то, что вы можете понять, что может быть асинхронной операцией. Вы в основном полагаться на людях, реализующих эти методы асинхронных фактически разоблачить истинные асинхронную операцию, а не лежат к вам с «фальшивым асинхронностью» с использованием Task.Run и т.д.

Например, этот метод Task возвращения:

public Task<string> DoHeavyLiftingAsync() 
{ 
    var tcs = new TaskCompletionSource<string>(); 
    string result = SomeHeavyWork(); 
    return tcs.SetResult(result); 
} 

В принципе, не выполнялись асинхронные операции. Может ли это случиться? Да, если кто-то, кто его реализует, не понимает, что он гарантирует вызывающему, это может случиться.

Если нет, то каковы наилучшие методы для вызова методов асинхронного программирования до , чтобы обеспечить неблокирующее поведение? (Особенно при вызове стороннего производителя библиотеку?

Как правило, вы можете доверять реализации должны асинхронное в BCL, чтобы обеспечить вам истинное асинхронность (хотя, you may be surprised at times). Если вы используете сторонний API, вы всегда можете посмотреть на код с помощью декомпилятора .NET, чтобы увидеть, что происходит на самом деле за кулисами. Если после этого вы все еще не уверены, вы всегда можете обернуть вызов Task.Run. Убедитесь, что вы используете это как в крайнем случае.

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