У меня есть следующий код в
private void Button_Click(object sender, EventArgs e)
{
try
{
Task.Run(async () => await Presenter.Search());
}
catch (Exception ex)
{
LabelMessage.Text = "Error:....";
}
}
Функция Presenter.Search() в некоторых случаях может получать исключения, и я хочу показать сообщение об ошибке. Однако исключение не возникло? Я вижу это только в отладчике Visual Studio.





На самом деле это должно быть написано так:
private async void Button_Click(object sender, EventArgs e)
{
try
{
await Presenter.Search();
}
catch (Exception ex)
{
LabelMessage.Text = "Error:....";
}
}
Теперь вызов ожидается, и исключение будет обработано правильно. Обратите внимание, что обычно вам не следует использовать async void по причинам, перечисленным здесь, но в случае обработчиков событий пользовательского интерфейса это рекомендуемый подход.
Мой код сложнее этого. Код фактически запускается таймером в конструкторе. Думаю, мне нужно будет задать новый вопрос
@ ca9163d9 Я тоже так думаю. Ваш вопрос должен точно соответствовать тому, что вам нужно сделать, а также описывать соответствующие обстоятельства (таймер).
Прежде всего, если Presenter.Search уже возвращает Task, вам следует подумать о том, чтобы сделать обработчик событий async и просто поместить
await Presenter.Search();
в блоке try-catch.
Причина существования перегрузки Task.Run(Func<Task>) заключается в том, что вы можете принудительно запланировать выполнение уже существующего Task в потоке пула. Этот случай может быть оправдан в очень редких случаях, поскольку обычно вы должны полагаться на внутреннюю реализацию методов возврата Task. Но если вы знаете, что асинхронный метод не использует потоки (например, просто возвращает Task, который будет завершен при определенном событии), и вы достаточно уверены в принудительном выполнении потока пула, вы можете сделать это таким образом. Но и в этом случае вам следует дождаться внешней задачи; в противном случае вызов будет беспрепятственным, и вы ничего не поймаете:
await Task.Run(() => Presenter.Search());
Обратите внимание, что я пропустил внутренний async-await:
await Task.Run(async () => await Presenter.Search());
Это также будет работать и функционально эквивалентно предыдущей версии, но добавляет ненужный внутренний конечный автомат в цепочку выполняемых задач.
TL; DR: Без дополнительных сведений await Presenter.Search(); кажется лучшим решением, но и await Task.Run(() => Presenter.Search()); может быть оправдан, если вы знаете, что делаете.
Он работает асинхронно, вы не используете
await, какTask.Runдолжен генерировать исключение, которое когда-нибудь произойдет в будущем?