Как изящно восстановить из TargetInvocationException в многопоточности? - PullRequest
2 голосов
/ 09 марта 2009

Я получил TargetInvocationException при выполнении длинного процесса в другом потоке, вызванном элементом управления Windows в потоке пользовательского интерфейса (индикатор выполнения). Это исключение приводит к сбою моего приложения (переход к основному методу при отладке) и не может быть перехвачено попыткой catch. Я выяснил, что сделало это исключение, и исправил его (пытался присвоить свойству «Значение» значение, превышающее максимум). Но это заставило меня задуматься, как я могу поймать исключение, подобное этому (в рабочем коде), поэтому у меня есть возможность восстановить свое приложение вместо завершения приложения.

Ответы [ 4 ]

2 голосов
/ 10 марта 2009

Вы можете «обрабатывать» исключения (на самом деле, вы просто получаете уведомление о них) в потоке GUI через статическое событие Application.UnhandledException.

Когда вы присоединяете обработчик к этому событию, он будет вызываться для всех необработанных исключений в потоке пользовательского интерфейса WinForms. Тот факт, что у вас есть этот обработчик, означает, что Application не выйдет. Без этого WinForms закрывает ваше приложение.

2 голосов
/ 09 марта 2009

Скорее всего, вы не сможете выздороветь очень сильно. С точки зрения вашей работы, состояние большого количества кадров стека (и объектов, на которые ссылаются эти стеки), вероятно, недопустимо из-за ошибки.

В связи с этим в лучшем случае вы можете восстановиться на очень высоком уровне и повторить операцию.

Если ресурсы, к которым вы обращаетесь, могут содержаться в транзакции, я бы посоветовал сделать это, чтобы вам не пришлось беспокоиться о несоответствиях в постоянных данных.

Кроме того, вы можете проверить эту тему на SO:

Рекомендации по обработке исключений в приложении Windows Forms?

А также блок приложения обработки исключений от Microsoft:

http://msdn.microsoft.com/en-us/library/cc309505.aspx

0 голосов
/ 10 марта 2009

Не уверен, какую версию .net вы используете, если его 3.0+, вы можете что-то сделать в этом направлении.

private void UpdateValue(int newValue)
{
    Action myAction = () => progressBar.Value = newValue;

    if (progressBar.InvokeRequired)
        progressBar.Invoke(myAction);
    else
        myAction();
}

Вызовите этот метод с новым значением для индикатора выполнения, который проверит, требует ли вызов маршалинга, и сделает соответствующий вызов. Будьте осторожны, InvokeRequired относительно дорог, поэтому используйте его только там, где это необходимо. Вы можете превратить это в метод расширения, чтобы при необходимости использовать этот шаблон для других элементов управления.

Надеюсь, это поможет.

0 голосов
/ 09 марта 2009

Перехватите исключение и найдите механизм для передачи его обратно в основной или вызывающий код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...