В своей практике я часто встречаю, в различном окружении, код вроде того, что приведен ниже:
[1] var x = FooWithResultAsync(/*...*/).Result;
//или
[2] FooAsync(/*...*/).Wait();
//или
[3] FooAsync(/*...*/).GetAwaiter().GetResult();
//или
[4] FooAsync(/*...*/)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
//или
[5] await FooAsync(/*...*/).ConfigureAwait(false)
//или просто
[6] awiat FooAsync(/*...*/)
Из общения с авторами таких строк, стало ясно, что все они делятся на три группы:
- Первая группа, это те, кому ничего не известно о возможных проблемах с вызовом
Result/Wait/GetResult
. Примеры (1-3) и, иногда, (6), типичны для программистов из этой группы;
- Ко второй группе относятся программисты, которым известно о возможных проблемах, но они не знают причин их возникновения. Разработчики из этой группы, с одной стороны, стараются избегать строк вроде (1-3 и 6), но, с другой, злоупотребляют кодом вроде (4-5);
- Третья группа, по моему опыту самая малочисленная, это те программисты, которые знают о том, как код (1-6) работает, и, поэтому, могут сделать осознанный выбор.
Возможен ли риск, и на сколько он велик, при использовании кода, как в приведенных выше примерах, зависит, как я отмечал ранее, от окружения.
Читать полностью »