Почему отладка отличается от запуска без отладки (отмена задачи)? - PullRequest
0 голосов
/ 23 августа 2010

Я сделал программу для тестирования параллельного программирования в C # 4.0. Однако есть проблема, и я не могу понять, почему.

Я пишу метод

    private void compute(int startValue, int endValue, ConcurrentBag<Pair> theList)
    {
        try
        {
            Task computation = Task.Factory.StartNew(() => { findFriendlyNumbers(startValue, endValue, theList, tokenSource.Token); }, tokenSource.Token);
            Task.WaitAll(computation);
            StringBuilder builder = new StringBuilder();
            foreach (Pair p in theList)
            {
                builder.AppendLine(p.ToString());
            }

            this.textBlockResult.Dispatcher.Invoke(new Action(() =>
            {
                this.textBlockResult.Text = builder.ToString();
                this.progressBar1.Visibility = System.Windows.Visibility.Hidden;
            }));
        }
        catch (AggregateException aEx)
        {
            MessageBox.Show("Entering");  //For debug, but never runs
            aEx.Handle(handleCancelling);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

Который запускается в отдельном потоке (кроме потока пользовательского интерфейса).

И функция (упрощенная)

        private void findFriendlyNumbers(int start, int end, ConcurrentBag<Pair> list, CancellationToken token)
    {
        //some initialization and computation

        for (int i = start; i <= end; i++)
        {
            //check whether it's cancelled
            token.ThrowIfCancellationRequested();

            //some computation
        }
    }

Проблема в том, что при отмене tokenSource будет возникать ошибка «OperationCanceledException не обрабатывается кодом пользователя», как если бы блок catch не существовал. Я не уверен, почему, потому что мой код похож на код в учебнике, а также в MSDN.

Спасибо.

EDIT: Я написал аналогичную программу меньше месяца назад, и тогда все было хорошо. Сегодня я попытался запустить его снова, такая же проблема произошла. Я установил Microsoft Visual Web Developer 2010 Express после завершения программы, и я не уверен, является ли это причиной. Я не понимаю, тот же код, разные результаты.

EDIT: Я подумал об этой проблеме и нашел, где не так. Раньше я использовал «запустить без отладки», а сейчас использую отладку. Запуск без отладки решает проблему. И я буду признателен, если кто-нибудь скажет мне, почему отладка отличается от «запустить без отладки».

1 Ответ

1 голос
/ 23 августа 2010

Вы передаете токен отмены методу TaskFactory.StartNew. Это заставляет Task обращаться с ним особенно: как с указанием отмены вместо ошибки.

Если вы не передадите токен как параметр в TaskFactory.StartNew, он будет считаться ошибкой и перехватываться. Если вы сохраните его в качестве параметра, то вам необходимо проверить отмену, используя Task.IsCanceled вместо исключения.

Примечание: лучше не использовать Invoke для синхронизации с потоком пользовательского интерфейса. У меня есть пример Task объектов, правильно выполняющих обновления пользовательского интерфейса в моем блоге.

...