Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/15: Рейтинг темы: голосов - 15, средняя оценка - 4.67
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173

Отмена async Task

08.04.2015, 21:32. Показов 3147. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Хочу:
1) запускать асинхронный метод = ok
2) выводить в textbox процесс работы = ok
3) ждать завершения работы = ok
4) после завершения работы выводить время работы = ok

5) иметь возможность останавливать метод по нажатию кнопки = проблема

Имеем такой код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        CancellationTokenSource source = new CancellationTokenSource();
        CancellationToken token = new CancellationToken();
 
 
        public Form1()
        {
            InitializeComponent();
            token = source.Token;
        }
 
        //пуск
        private void button1_Click(object sender, EventArgs e)
        {
            RunIt();
        }
 
        //отмена
        private void button2_Click(object sender, EventArgs e)
        {
            source.Cancel();
        }
 
        //запускаем таску
        private async Task<string> RunIt()
        {
            DateTime dt = DateTime.Now;
 
            Task<string> task = Task.Factory.StartNew(() =>
            {
                Parallel.ForEach(Files, file =>
                {
                    token.ThrowIfCancellationRequested();
 
                    textBox1.Invoke((Action)delegate { textBox1.AppendText(file + "\n"); });
                    ParseFile(file);
                });
 
                return "Проверка завершена";
 
 
            }, token);
 
            string result = await task;
            textBox2.Text = (DateTime.Now - dt).TotalSeconds.ToString();
            textBox1.AppendText(result + "\r\n");
            return result;
 
       }

При нажатии кнопки отмены на строчке
C#
1
token.ThrowIfCancellationRequested();
появляется ошибка:
An exception of type 'System.OperationCanceledException' occurred in mscorlib.dll but was not handled in user code
Вопрос N 1. Подскажите, в каком месте кода ошибка, что нужно сделать, чтобы нормально обрабатывать этот эксепшн?

Добавлено через 2 минуты
Вопрос N 2. Возможно ли в любой момент проверить, выполняется в данный момент task или нет? Или это можно сделать, только устанавливая и снимая флаги в начале и конце таска?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.04.2015, 21:32
Ответы с готовыми решениями:

Task.Wait async Метод
Всем привет. Нужна помощь. Я в сеттере (нужно именно тут) создаю таск Task task = new Task(Load); Сам лоад асинхронный: private...

Возврат нескольких переменных из метода с async Task
Пытаюсь реализовать возврат двух переменных, компилятор выдает ошибку: Ошибка CS1001 Требуется идентификатор. static async...

Task на Task или масло масленное?
Сделал вот такую штуку, хз не лишканул ли? await Task.Factory.StartNew(() =&gt; { ...

14
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 21:49
Цитата Сообщение от Suppir Посмотреть сообщение
в каком месте кода ошибка
Строка 32, именно там где вы и генерируете Exception().
Цитата Сообщение от Suppir Посмотреть сообщение
что нужно сделать, чтобы нормально обрабатывать этот эксепшн?
Цитата Сообщение от Suppir Посмотреть сообщение
нормально обрабатывать этот эксепшн
То есть использовать try{}catch{}
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 21:54  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
То есть использовать try{}catch{}
а в каком именно месте использовать try{} catch{}? На самом таске или на Parallel.ForEach?

Добавлено через 3 минуты
Я пробовал так:

C#
1
2
3
4
5
6
7
8
  try
            {
                result = await task;
            }
            catch (AggregateException e)
            {
                result = "Проверка отменена";
            }
Но та же ошибка остается.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 21:57
Цитата Сообщение от Suppir Посмотреть сообщение
в каком именно месте использовать try{} catch{}?
Внутри Parallel.ForEach() попробуйте.
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:00  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Внутри Parallel.ForEach() попробуйте.
То же самое. Пробовал внутри Parallel.ForEach(), снаружи его, снаружи определения Task, вокруг "await task" - но одна и та же ошибка получается.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 22:02
Цитата Сообщение от Suppir Посмотреть сообщение
То же самое.
А сама строка token.ThrowIfCancellationRequested() внутри блока try{}catch{}?
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:05  [ТС]
Все, понял!!

Вы подсказали правильно - внутри Parallel.ForEach. Но только я ошибочно написал:
C#
1
catch (AggregateException e){}
//взял отсюда: https://msdn.microsoft.com/ru-... .110).aspx


А нужно было написать
C#
1
catch (OperationCanceledException e){}

Хотелось бы получить ответ на второй вопрос:
возможно ли в любой момент проверить, выполняется в данный момент task или нет? Или это можно сделать, только устанавливая и снимая флаги в начале и конце таска?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 22:07
И самое главное, что мне не совсем понятно в вашем коде - зачем вы мешаете в одну кучу Task, async-await и еще Parallel.ForEach() вдобавок?
У меня складывается впечатление, что проблему можно решить элегантнее.

Добавлено через 1 минуту
Цитата Сообщение от Suppir Посмотреть сообщение
возможно ли в любой момент проверить, выполняется в данный момент task или нет?
Если в методе, который вы используете в Parallel.ForEach() определить к-либо событие и бросать его, думаю можно.
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:12  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
И самое главное, что мне не совсем понятно в вашем коде - зачем вы мешаете в одну кучу Task, async-await и еще Parallel.ForEach() вдобавок?
У меня складывается впечатление, что проблему можно решить элегантнее.
Мне нужно обрабатывать много файлов. При этом чтобы:
- не подвешивалась главная форма;
- промежуточные результаты выводились в textbox;
- можно было отменить обработку в любой момент;
- сразу по окончании работы выполнить другую работу.

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

Чтобы Parallel.Foreach не подвешивал форму программы, я его запускаю через Task.

async-await нужен для того, чтобы сразу после выполнения таска можно было выполнить какое-то действие (в моем случае - вывести что-то на экран). Это можно сделать через task.continuewith, но тогда код получается совсем непонятным.

Если указанные задачи можно решить как-то элегантнее, то мне бы очень хотелось узнать, как это сделать
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 22:23
Цитата Сообщение от Suppir Посмотреть сообщение
- не подвешивалась главная форма;
Thread-Task.StartNew()
Цитата Сообщение от Suppir Посмотреть сообщение
- промежуточные результаты выводились в textbox;
event-ы изнутри метода-цели
Цитата Сообщение от Suppir Посмотреть сообщение
- можно было отменить обработку в любой момент;
CancellationTokenSource()
Цитата Сообщение от Suppir Посмотреть сообщение
- сразу по окончании работы выполнить другую работу.
Task.ContinueWith()

Добавлено через 1 минуту
И самое главное - инкапсулировать все в отдельном классе, не мешая логику обработки и UI.
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:25  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
Task.ContinueWith()
Пробовал - получается еще более сложный код. Поэтому решил async - так приятней выглядит.

Цитата Сообщение от insite2012 Посмотреть сообщение
Thread-Task.StartNew()
О различиях между тасками и Parallel.ForEach я прочитал здесь:

http://stackoverflow.com/quest... y-startnew

The first (Parallel.ForEach ) is a much better option.

Parallel.ForEach, internally, uses a Partitioner<T> to distribute your collection into work items. It will not do one task per item, but rather batch this to lower the overhead involved.

The second option will schedule a single Task per item in your collection. While the results will be (nearly) the same, this will introduce far more overhead than necessary, especially for large collections, and cause the overall runtimes to be slower.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 22:29
Suppir, если уж вам так необходимо параллельное выполнение, то почему вы не обратили внимание на PLINQ?
Он имеет возможности более тонкой настройки секционирования, да и сам по себе удобнее.
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:34  [ТС]
Я еще даже LINQ не изучал, так как все время программировал на .NET Framework 2.0 (для удобства пользователей). На PLINQ даже не заглядывался
Сейчас, вот, решил одну программу на .NET Framework 4.0 переписать, т.к. сильно нужны Task'и.

А как можно применить PLINQ к указанной задаче? Я думал, что PLINQ нужен для запросов, по типу SQL, но которые выполняются многопоточно.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
08.04.2015, 22:38
Цитата Сообщение от Suppir Посмотреть сообщение
А как можно применить PLINQ к указанной задаче?
Да как и обычный. Только указать метод расширения AsParallel(). Или, в зависимости от того, какой размер коллекции для обработки, создать и использовать Partitioner. Вариантов там достаточно. Смотрите по ссылке ниже.
Ну и главное - используйте инкапсуляцию, уберите все в отдельный класс (классы), не мешайте бизнес-логику и отображение.
http://rsdn.ru/article/dotnet/... _3.xml#EZG
0
28 / 28 / 11
Регистрация: 08.08.2011
Сообщений: 1,173
08.04.2015, 22:40  [ТС]
Спасибо, почитаю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.04.2015, 22:40
Помогаю со студенческими работами здесь

[UWP] Возвращаемым типом асинхронного метода должен быть void, Task или Task<T>
Создал асинхронный метод. Он должен на выходе вывести объект который состоит из строк. Пишет ошибка, что можно сделать? Первый скрин с...

Отмена одного Task в массиве Task
Как можно отменить одну задачу в массиве Task? Никак же нельзя передать CancellationTokenSource в массиве?

Task и async-await
Объясните пожалуйста, в чем преимущество async-await? И в чем разница между обычной задачей? Ведь задачи то же выполняются независимо друг...

Многопоточность с async/await и Task
Помогите разобраться с многопоточностью, совсем запутался после чтения множества статей. Нужно использовать async/await или таски. ...

Отмена Task
Добрый день, у меня очередной вопрос к Гуру..) Есть Таск, который можно отменить извне с помощью CancellationToken. Таском...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru