Получить Exception из BackgroundWorker

369
03 августа 2017, 22:17

Перерыл интернет и не смог найти ответа на свой вопрос. Использую backgroundworker, запускаю его в работу таким методом
async void bw_DoWork(object sender, DoWorkEventArgs e)

Мне нужно выловить ошибку из этого метода в основной поток, для этого дописал

bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            MessageBox.Show("Произошла ошибка: " + e.Error.ToString());
        }
    }

Но ошибка не ловится. Подозреваю, что из-за того, что метод async.

Answer 1

Автор, async и await призваны как раз исключить необходимость использования BackgroundWorkerов и иже с ними. Зачем ты скрещиваешь эти независимые парадигмы? async метод порождает фоновую задачу. Исключения в процессе её выполнения сохраняются в контейнер Task. Если ты назначаешь продолжение посредством await, то оно будут выброшено наверх (или Wait/Result, которые для асинхронных задач использовать строго не рекомендуется). В противном случае - нет. Убери async и будет тебе счастье. Если этот метод используют, как BackgroundWorker, так и цепочка асинхронных вызовов, сделай два метода - один с модификатором async, а другой без него.

Answer 2

Есть ли безусловная необходимость в использовании Backgroundworker?

Если необходимо выделить поток для задачи с нагрузкой на CPU можно, например, сделать следующим образом

private async Task DoWork()
{
    try
    {
        await Task.Run(() =>
        {
            DoMyCpuIntensiveWork();
        });
    }
    catch (MyWorkException1 mwex1)
    {
        ShowExceptionMessage(mwex1.ToString());
    }
    catch (MyWorkException2 mwex2)
    {
        ShowExceptionMessage(mwex2.ToString());
    }
}
private void ShowExceptionMessage (string errorMessage)
{
    MessageBox.Show("Произошла ошибка: " + errorMessage);
}

Таким образом исключения должны ловиться в вызывающем потоке.

Если вызываемый метод async, то можно и сразу так сделать

private async Task DoWork()
{
    try
    {
        await DoMyWorkAsync();
    }
    catch (MyWorkException1 mwex1)
    {
        ShowExceptionMessage(mwex1.ToString());
    }
    catch (MyWorkException2 mwex2)
    {
        ShowExceptionMessage(mwex2.ToString());
    }
}
private void ShowExceptionMessage (string errorMessage)
{
    MessageBox.Show("Произошла ошибка: " + errorMessage);
}
READ ALSO
Использование команд и сервисной шины

Использование команд и сервисной шины

Предположим, есть веб-сервис, который принимает POST-запрос на регистрацию пользователяПервоначальная реализация (намеренно очень упрощенная):

353
Не отображает Particle sysme в 2Д игре

Не отображает Particle sysme в 2Д игре

Привет! создал первую 2Д игру, добавил партиклы, но они не отображаются над картинкой

221
Как отключить передвижение заголовков Pivot'а?

Как отключить передвижение заголовков Pivot'а?

Пытаюсь создать Pivot табамиВроде бы как все закончил, но из за того что элементы примыкают к краям приложения они начинают "бегать"

259