Это не дубликат «Как безопасно вызвать асинхронный метод в C # без ожидания» .
Как мне приятно подавить следующее предупреждение?
предупреждение CS4014: поскольку этот вызов не ожидается, выполнение текущего метода продолжается до завершения вызова. Попробуйте применить оператор 'await' к результату вызова.
Простой пример:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Что я пробовал и не понравилось
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Обновленный , так как исходный принятый ответ был отредактирован, я изменил принятый ответ на тот, который использует C # 7.0 , поскольку я не думаю, что ContinueWith
здесь уместно. Всякий раз, когда мне нужно регистрировать исключения для операций запуска и забывания, я использую более сложный подход, предложенный Стивеном Клири здесь .
c#
async-await
noseratio
источник
источник
#pragma
не приятно?async void
вспомогательного метода.Ответы:
С C # 7 теперь вы можете использовать сброс :
источник
_ = ...
в моем мозгу.#pragma warning disable CSxxxx
выглядит более уродливо, чем сброс;)Вы можете создать метод расширения, который предотвратит предупреждение. Метод расширения может быть пустым, или вы можете добавить обработку исключений
.ContinueWith()
там.Однако ASP.NET подсчитывает количество запущенных задач, поэтому он не будет работать с простым
Forget()
расширением, как указано выше, и вместо этого может произойти сбой за исключением:В .NET 4.5.2 это можно решить с помощью
HostingEnvironment.QueueBackgroundWorkItem
:источник
TplExtensions.Forget
. Там намного больше добраMicrosoft.VisualStudio.Threading
. Мне бы хотелось, чтобы он был доступен для использования вне Visual Studio SDK.Вы можете украсить метод следующим атрибутом:
По сути, вы говорите компилятору, что знаете, что делаете, и вам не нужно беспокоиться о возможной ошибке.
Важной частью этого кода является второй параметр. Часть «CS4014:» - это то, что подавляет предупреждение. Вы можете написать все, что вы хотите на отдыхе.
источник
[SuppressMessage("Compiler", "CS4014")]
подавляет сообщение в окне списка ошибок, но в окне вывода по-прежнему отображается строка предупрежденияМой два способа борьбы с этим.
Сохраните его в переменную сброса (C # 7)
пример
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);
С момента появления сбросов в C # 7 я теперь считаю, что это лучше, чем подавление предупреждения. Потому что оно не только подавляет предупреждение, но и проясняет намерение «забей и забудь».
Более того, компилятор сможет оптимизировать его в режиме релиза.
Просто подавь это
это достаточно хорошее решение, чтобы «выстрелить и забыть».
Причина появления этого предупреждения заключается в том, что во многих случаях вы не собираетесь использовать метод, который возвращает задачу, не ожидая ее. Подавление предупреждения, когда вы намерены выстрелить и забыть, имеет смысл.
Если у вас возникли проблемы с запоминанием написания
#pragma warning disable 4014
, просто позвольте Visual Studio добавить его для вас. Нажмите Ctrl +. открыть «Быстрые действия», а затем «Подавить CS2014»В целом
Глупо создавать метод, для выполнения которого требуется еще несколько тиков, просто с целью подавления предупреждения.
источник
[MethodImpl(MethodImplOptions.AggressiveInlining)] void Forget(this Task @this) { } /* ... */ obj.WorkAsync().Forget();
AggressiveInlining
компилятор, по какой-то причине просто игнорирую его#pragma warning disable 4014
а затем восстановить предупреждение с помощью#pragma warning restore 4014
. Он по-прежнему работает без кода ошибки, но если вы не добавите номер ошибки, он подавит все сообщения.Простой способ остановить предупреждение - просто назначить задачу при ее вызове:
И так в вашем оригинальном посте вы бы сделали:
источник
task
выглядит как забытая локальная переменная. Почти как компилятор должен дать мне другое предупреждение, что-то вроде «task
назначено, но его значение никогда не используется», кроме того, это не так. Кроме того, это делает код менее читабельным. Я сам использую этот подход.fireAndForget
... так что я ожидаю, что отныне оно не будет ссылаться.Причиной предупреждения является то, что WorkAsync возвращает значение
Task
, которое никогда не читается и не ожидается. Вы можете установить тип возврата WorkAsync,void
и предупреждение исчезнет.Обычно метод возвращает a,
Task
когда вызывающая сторона должна знать статус работника. В случае «забывай и забывай», void должен быть возвращен, чтобы напоминать, что вызывающая сторона независима от вызываемого метода.источник
Почему бы не обернуть его внутри асинхронного метода, который возвращает void? Немного длинный, но все переменные используются.
источник
Я нашел этот подход случайно сегодня. Вы можете определить делегата и назначить асинхронный метод делегату первым.
и называть это так
...
Я подумал, что интересно, что компилятор не будет выдавать точно такое же предупреждение при использовании делегата.
источник
(new Func<Task>(AsyncOperation))()
хотя IMO все еще слишком многословен.