Выполнение задач с обработкой исключений при обновлении GUI во время задач - PullRequest
0 голосов
/ 29 февраля 2012

Утро.

(Попытка сделать): Я пытаюсь выполнить несколько задач параллельно.Каждая задача проходит через определенный раздел текстового файла с использованием цикла for (1-я задача = строки 1–10. 2-я задача = строки 11–20 и т. Д.).В конце каждой проверки строки возникает событие, и поток графического интерфейса обновляет пользовательский интерфейс, т. Е. «X строк проверено».

(Застрял): я не понимаю, как это сделать, и все же будув состоянии обрабатывать исключения правильно.Насколько мне известно, мне нужно позвонить

task.Wait();  

или

task.WaitAll();

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

Кто-нибудь знает, как обойти это?

Примечание: Я заранее извиняюсь, если это глупо, но у меня есть некоторые проблемы с многопоточностью.

, поскольку задачи связывают все исключения в AggregateException и если я вызываю task.Waitall ();кажется, что поток пользовательского интерфейса просто ждет, пока задачи не будут выполнены или не будет сгенерировано исключение.

Ответы [ 2 ]

1 голос
/ 29 февраля 2012

Один из вариантов - присоединить к вашей задаче другую задачу как «обработчик» для обработки любых исключений.

Вот пример:

var task = Task.Factory.StartNew(() =>
{
    throw new Exception("oops!");
});

// attach an exception-handling task
task.ContinueWith(previousTask =>
{
    // do something with the exception
    Console.WriteLine(previousTask.Exception);      

}, TaskContinuationOptions.OnlyOnFaulted);

Обратите внимание, что задача, прикрепленная с ContinueWith, имеет TaskContinuationOptions.OnlyOnFaulted, что означает, что она будет выполняться только в том случае, если задача, к которой она прикреплена, выдает исключение.

Таким образом, ваши исключения могут обрабатываться асинхронно, и вам не нужно ничего ждать.

Однако, так как вы хотите провести параллель для цикла, я бы, вероятно, сделал что-то вроде:

Task.Factory.StartNew(() =>
{
    try 
    {
        Parallel.For(..., i => 
        {
            ... 
        });
    }
    catch (AggregateException e)
    {
        // handle it somehow
    }
});

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

Главное, в чем вы должны быть уверены, это то, что ваше предложение catch (или задача обработки в предыдущем примере) никогда не вызывает исключение.

0 голосов
/ 29 февраля 2012

Одна альтернатива (самая простая) - обработать исключение в потоке, который его выдал.

Так что вам понадобится попытка перехвата в методе выполнения - тогда то, что вы делаете, зависит от вашего дизайна, выможет, например, вызвать событие ошибки, которое может обработать пользовательский интерфейс (все еще в контексте потока исключений).

Другая альтернатива состоит в том, что вы можете запустить свой код планирования задач (то есть код, который вызывает WaitAll ()) в качестве BackgroundWorker - тогда пользовательский интерфейс будет свободен для выполнения своих задач (обработки другого ввода) - это, вероятно, лучший способ сделать это, но может потребовать небольшого перефакторинга.

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