CA2007: не ожидайте непосредственно задачи
Свойство | Значение |
---|---|
Идентификатор правила | CA2007 |
Заголовок | Не следует напрямую ожидать Task |
Категория | Надежность |
Исправление является критическим или не критическим | Не критическое |
Включен по умолчанию в .NET 8 | No |
Причина
Асинхронный метод ожидает класс Task напрямую.
Описание правила
Когда асинхронный метод ожидает класс Task напрямую, продолжение обычно происходит в том же потоке, который создал задачу, в зависимости от асинхронного контекста. Такое поведение может быть дорогостоящим в плане производительности и может привести к взаимоблокировке потока пользовательского интерфейса. Чтобы сообщить о намерении продолжения, рассмотрите возможность вызова метода Task.ConfigureAwait(Boolean).
Устранение нарушений
Чтобы устранить нарушения, вызовите метод ConfigureAwait для ожидаемого класса Task. Параметру continueOnCapturedContext
можно передать значение true
или false
.
Поведение вызова
ConfigureAwait(true)
для задачи аналогично поведению неявного вызова ConfigureAwait. Вызывая этот метод явным образом, вы даете понять читателям, что намеренно хотите продолжать выполнение в исходном контексте синхронизации.Вызовите
ConfigureAwait(false)
для задачи, чтобы запланировать продолжение в пуле потоков и избежать тем самым взаимоблокировки в потоке пользовательского интерфейса. Передачу значенияfalse
целесообразно использовать для библиотек, независимых от приложений.
Пример
Следующий фрагмент кода приводит к возникновению предупреждения:
public async Task Execute()
{
Task task = null;
await task;
}
Чтобы устранить нарушение, вызовите метод ConfigureAwait для ожидаемого класса Task:
public async Task Execute()
{
Task task = null;
await task.ConfigureAwait(false);
}
Когда лучше отключить предупреждения
Это предупреждение предназначено для библиотек, где код может выполняться в произвольных средах и не должен делать предположений о среде или о том, как вызывающий объект метода может вызываться или ожидать метод. Как правило, рекомендуется полностью подавлять вывод предупреждения для проектов, представляющих код приложения, а не код библиотеки. На самом деле запуск анализатора в коде приложения (например, обработчики событий нажатия кнопки в проекте WinForms или WPF), скорее всего, приведет к выполнению неправильных действий.
Вывод этого предупреждения можно отключить в любой ситуации, когда продолжение выполнения должно быть запланировано в исходном контексте, или при отсутствии такого контекста. Например, при написании кода в обработчике событий нажатия кнопки в приложении WinForms или WPF в общем случае продолжение из ожидания должно выполняться в потоке пользовательского интерфейса, и, таким образом, желательным поведением по умолчанию будет планирование продолжения выполнения обратно в исходном контексте. Другой пример: при написании кода в приложении ASP.NET Core по умолчанию отсутствует SynchronizationContext или TaskScheduler, поэтому ConfigureAwait
не приведет к изменению поведения.
Отключение предупреждений
Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.
#pragma warning disable CA2007
// The code that's violating the rule is on this line.
#pragma warning restore CA2007
Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none
в файле конфигурации.
[*.{cs,vb}]
dotnet_diagnostic.CA2007.severity = none
Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.
Настройка кода для анализа
Используйте следующие параметры, чтобы указать части базы кода, к которым будет применяться это правило.
Все эти параметры можно настроить только для этого правила, для всех правил, к которым она применяется, или для всех правил в этой категории (надежность), к которым она применяется. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.
Исключение асинхронных методов void
Можно настроить, следует ли исключать асинхронные методы, которые не возвращают значение из этого правила. Чтобы исключить эти типы методов, добавьте следующую пару "ключ-значение" в файл .editorconfig в проекте:
# Package version 2.9.0 and later
dotnet_code_quality.CA2007.exclude_async_void_methods = true
# Package version 2.6.3 and earlier
dotnet_code_quality.CA2007.skip_async_void_methods = true
Тип вывода
Можно также настроить типы выходных сборок, к которым применяется это правило. Например, чтобы применить это правило только к коду, который создает консольное приложение или динамически связанную библиотеку (то есть не приложение пользовательского интерфейса), добавьте следующую пару "ключ-значение" в файл .editorconfig в проекте:
dotnet_code_quality.CA2007.output_kind = ConsoleApplication, DynamicallyLinkedLibrary