Task.Run () не вызывает исключение?

У меня есть следующий код в

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.

Он работает асинхронно, вы не используете await, как Task.Run должен генерировать исключение, которое когда-нибудь произойдет в будущем?

tkausl 16.11.2018 19:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
139
2

Ответы 2

На самом деле это должно быть написано так:

private async void Button_Click(object sender, EventArgs e)
{
    try
    {
        await Presenter.Search();
    }
    catch (Exception ex)
    {
        LabelMessage.Text = "Error:....";
    }
}

Теперь вызов ожидается, и исключение будет обработано правильно. Обратите внимание, что обычно вам не следует использовать async void по причинам, перечисленным здесь, но в случае обработчиков событий пользовательского интерфейса это рекомендуемый подход.

Мой код сложнее этого. Код фактически запускается таймером в конструкторе. Думаю, мне нужно будет задать новый вопрос

ca9163d9 16.11.2018 19:21

@ ca9163d9 Я тоже так думаю. Ваш вопрос должен точно соответствовать тому, что вам нужно сделать, а также описывать соответствующие обстоятельства (таймер).

user47589 16.11.2018 19:24

Прежде всего, если 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()); может быть оправдан, если вы знаете, что делаете.

Другие вопросы по теме