Чому C # дозволяє вам зробити асинхронізацію заміни?


16

У C #, коли ви переосмислюєте метод, дозволено робити асинхронізацію override, коли оригінальний метод не був. Це здається поганою формою.

Приклад, який привів мене до цього, був таким - мене запросили, щоб допомогти у вирішенні проблеми з навантаженням. Приблизно 500 одночасних користувачів процес входу в систему переривається в циклі переадресації. IIS реєстрував винятки з повідомленням "Асинхронний модуль або обробник виконаний, поки асинхронна операція ще тривала". Деякі пошуки змусили мене думати, що хтось зловживає async void, але мій швидкий пошук у джерелі нічого не міг знайти.

На жаль, я шукав "async \ svoid" (пошук регулярних виразів), коли мені слід було шукати щось подібне до "async \ s [^ T]" (якщо припустити, що завдання не повністю кваліфіковане ... ви отримаєте бал).

Пізніше я знайшов async override void onActionExecuting(... у базовому контролері. Очевидно, що це мала бути проблема, і це було. Виправлення цієї проблеми (зробити її синхронною на даний момент) вирішило проблему.

Повернення до питання: Чому о, чому ви можете позначити переопределення як асинхронізацію, коли код виклику ніколи не може його чекати?



Що саме заважає абоненту чекати перекритого методу? Я не бачу перешкод.
Мартін Мейт

@MartinMaat Ви можете лише чекати методів, які повернуться Task.
Дерек Елкінс покинув SE

Можливо, це прекрасний момент, якого я не помічав. Мені доведеться перевірити, але я не пригадую попередження VS про виклик методів без асинхронізації без очікування.
Пітер Т. Лакомб-молодший

Відповіді:


16

Асинхронне ключове слово дозволяє метод використовувати awaitсинтаксис в його визначенні. Я можу awaitвикористовувати будь-який метод, який повертає Taskтип незалежно від того, чи це метод асинхронізації.

void є легальним (хоча і) відсторонений ) тип повернення для методу асинхронізації, то чому б це не було дозволено? Ззовні asyncне дає змоги нічого, що ви не могли б зробити без цього. Метод, з яким у вас виникають проблеми, міг бути написаний таким чином, щоб він поводився точно так само, не будучи асинхронним. Його визначення просто було б більш багатослівним.

Для абонентів, async Tметод є нормальним методом , який повертає T(який обмежений void, TaskабоTask<A> ). Те, що це метод асинхронізації, не є частиною інтерфейсу. Зауважте, що наступний код незаконний:

interface IFoo {
    async void Bar();
}

Він (або аналогічний код у абстрактному класі) видає таке повідомлення про помилку у VS2012:

Модифікатор 'async' може використовуватися лише в методах, що мають тіло оператора

Якщо я мав намір метод в інтерфейсі або батьківському класі бути типово асинхронним, я не можу використовувати це asyncдля спілкування. Якби я хотів реалізувати його за допомогою awaitсинтаксису, мені потрібно мати можливість асинхронізувати методи заміщення (у випадку батьківського класу).


1
Ви зовсім не згадуєте override, але це питання.
Натан Туггі

5
@NathanTuggy Вся суть відповіді полягає в тому, asyncщо не змінюється інтерфейс методу, лише те, що синтаксично дозволено в його визначенні, так що це переоцінка чи ні, абсолютно не має значення.
Дерек Елкінс покинув SE

1
Поясніть, будь ласка, це, а не припускаючи, що всі вже знають все відповідне
Натан Туггі

2
@NathanTuggy Я відчуваю, що я це пояснив. Чи можете ви задати конкретний запитання, щодо якого ви плутаєтесь, чи ви уявляєте, що інший розгублений чоловік би запитав? Єдине, що я можу додати, це зазначити, що asyncмодифікатор може застосовуватися лише до реалізацій. Ви не можете оголосити метод асинхронізації в інтерфейсі, наприклад, підкреслюючи, що метод є асинхронністю чи ні, не є частиною інтерфейсу.
Дерек Елкінс покинув SE

5
Поставте пояснення у відповідь , я маю на увазі. Це не те, що коментарі є в довгостроковій перспективі.
Натан Туггі

10

Єдина мета ключового слова async - зробити так, щоб очікувати всередині цієї функції ключове слово. Це потрібно, щоб додавання функції очікування не порушило існуючий код. Microsoft вирішила скористатися опцією очікування для вибору. Для функції, яка не позначена асинхронізацією, ви можете визначити змінну з назвою await без проблеми.

Отже, асинхронізація не є частиною підпису функції і не має семантичного значення в створеному коді IL. Саме компілятор знає, як правильно скомпілювати функцію. Він також доручає компілятору забезпечити повернення лише Завдання, Завдання <T> або недійсних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.