@CSharpChatЭта группа больше не существует

Страница 1268 из 1888
Летучая
18.06.2017
16:42:10
Боюсь таких картинок

Как огня

Alexander
18.06.2017
16:42:29
покажи пример как надо, я просто копипастил сам это

Летучая
18.06.2017
16:43:31
Убрать нечитаемые массивы и сделать обёрточку для итераций

Google
Влад
18.06.2017
16:47:09
Подниму чутка урон.

Чуть позже.

Igor
18.06.2017
16:48:47
Ну вы все таки сделайте отдельный чат или в @CSharpRest переместитесь, а тот тут не все дотеры.

Влад
18.06.2017
16:50:09
)(

Ты ток шо на урсе играл?

Anton
18.06.2017
16:58:31
Подскажите по CancellationToken. Как с ним правильно работать, чтобы не проверять на каждом шаге IsCancellationRequested?

Можно извне отменить таск, чтобы внутри него кинулся какой-нибудь CancellationRequestedException?

По типу Thread.Abort, только для тасков

Собственно такой эксепшен уже есть: OperationCanceledException, но сейчас его руками надо кидать, либо через token.ThrowIfCancellationRequested();. А это опять, получается, надо на каждом шаге писать. Хотелось бы, чтобы шедулер автоматически это делал

Роман
18.06.2017
17:08:44
Собственно такой эксепшен уже есть: OperationCanceledException, но сейчас его руками надо кидать, либо через token.ThrowIfCancellationRequested();. А это опять, получается, надо на каждом шаге писать. Хотелось бы, чтобы шедулер автоматически это делал
что-то мне подсказывает, что не получится, т.к. исключение должно быть брошено в потоке асинхронной операции, а значит этот поток должен что-то делать, например вызвать token.ThrowIfCancellationRequested();

Anton
18.06.2017
17:09:58
Мне кажется, что шедулер может

Он же это делает, когда прокидывает эксепшен из дочернего таска, когда его await'ишь

Роман
18.06.2017
17:12:37
Мне кажется, что шедулер может
если никакой магии нет, то шедулер не может, т.к. CancellationToken это просто объект, который никак не привязывается к потоку, а просто лежит на стеке с исключением в дочернем потоке хотя бы понятно как работает, т.к. проброска исключения мало чем отличается от проброски возвращаемого значения

Google
Anton
18.06.2017
17:13:18
Хм

Но шедулер же вроде знает о токене

Потому что он даже не запускает таск, если токен отменён заранее

То есть, грубо говоря, в момент очередного пробуждения таска, он может проверить, если токен, ассоциированный с таском, отменён, то кинуть эксепшен

Но это мои догадки, я не смотрел, как шедулер написан

Просто мне казалось, что должен быть уже готовый механизм для этого

После каждого await проверять токен, это ужасный boilerplate

Дмитрий
18.06.2017
17:17:03
насколько я помню, при запуске таска проверяется IsCancellationRequested у токена если true - таск не запускается и возвращается canceled task

вроде

Anton
18.06.2017
17:17:24
Ну да, он это делает в начале таска, при запуске

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

Это я к тому, что связь между таском и токеном где-то там хранится всё-таки

Летучая
18.06.2017
17:18:43
Полгода назад задался тем же вопросом, хотел найти красивое решение

Не нашёл

Роман
18.06.2017
17:19:08
Это я к тому, что связь между таском и токеном где-то там хранится всё-таки
да, ты прав, токен хранится в таске https://msdn.microsoft.com/ru-ru/library/dd783029(v=vs.110).aspx

Дмитрий
18.06.2017
17:19:17
https://msdn.microsoft.com/ru-ru/library/dd321635(v=vs.110).aspx

может так попробовать?

Anton
18.06.2017
17:19:52
Да, про Register я знаю

Через него как раз можно делать высвобождение ресурсов при отмене

Дмитрий
18.06.2017
17:20:58
зарегать у токена делегат на метод, внутри которого всё стопать, чистить ресурсы и бросаться CanceledException-ом

Google
Anton
18.06.2017
17:20:59
А вот прерывать выполнение руками приходится

Gid
18.06.2017
17:21:34
Anton
18.06.2017
17:21:39
Да, я тоже так думал, но вроде все зарегистрированные экшены выполняются в том потоке, откуда вызван Cancel

И эксепшен соответственно тоже

А мне бы его прокинуть в continuation

Ну или хотя бы просто заставить его не вызывать этот самый continuation

Потому что всю логику по отмене можно запихать в token.Register(), а в таске надо просто return сделать

Дмитрий
18.06.2017
17:25:15
Я как-то с необходимостью такого никогда раньше не сталкивался...

обычно просто в ключевых точках IsCancellationRequested проверял

Anton
18.06.2017
17:26:43
Ну да, только не в ключевых точках, а после каждого await. И если их много, то это боль, и код становится плохочитаемым

Как будто не продумали они этот механизм до конца

Роман
18.06.2017
17:38:24
Как будто не продумали они этот механизм до конца
возможно у тебя кейс слишком специфический. Мне кажется что стоит отменять в первую очередь в истинно асинхронных местах: ввод/вывод. Но там и так уже есть отмена.

Летучая
18.06.2017
17:39:40
Есть чат, есть список диалогов

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

И вот тут такая штука бы пригодилась

Anton
18.06.2017
17:40:58
возможно у тебя кейс слишком специфический. Мне кажется что стоит отменять в первую очередь в истинно асинхронных местах: ввод/вывод. Но там и так уже есть отмена.
Да вроде обычный кейс. Есть например окно, у которого очень долгая инициализация из нескольких шагов. Если окно закрыли, пока там всё грузилось, надо освободить всё, что успелось загрузиться, и не грузить дальше

Летучая
18.06.2017
17:41:24
Должен же быть какой-нибудь способ прибить таск

Летучая
18.06.2017
17:42:15
Вот если честно, то зачем? Это усложнение кода, которое особо ничего и недает.
Предлагаешь оставлять то, что не догрузилось, на произвол судьбы и работать с новым инстансом окна с диалогом?

Примерно на таком вроде и остановился я в прошлый раз.

Google
Igor
18.06.2017
17:44:19
Да вроде обычный кейс. Есть например окно, у которого очень долгая инициализация из нескольких шагов. Если окно закрыли, пока там всё грузилось, надо освободить всё, что успелось загрузиться, и не грузить дальше
Не сказал бы что это обычный кейс. Если у тебя >1 одной точки отката, то это уже сложно прописать (несколько стадий откатки). Обычно асинхронный операции содержат 1 долгую функцию или несколько мутирований засунутых в транзакцию.

Ilya
18.06.2017
17:46:13
Вообще обычное использование токена это в безопасный момент проверять его и бросать экзепшн, по другому никак не сделать

Anton
18.06.2017
17:46:19
Ну сейчас примерно вот так получается: { try { var resource1 = await Load1(); token.ThrowIfCancellationRequested(); var resource2 = await Load2(); token.ThrowIfCancellationRequested(); var resource3 = await Load3(); token.ThrowIfCancellationRequested(); } catch (OperationCanceledException) { if (resource1 != null) resource1.Dispose(); if (resource2 != null) resource2.Dispose(); if (resource3 != null) resource3.Dispose(); throw; } }

Hell
18.06.2017
17:46:36
ВASP.NET MVC не используется по умолчанию EF?

Admin
ERROR: S client not available

Влад
18.06.2017
17:47:04
Кароч, релиз откладывается.

Anton
18.06.2017
17:47:04
Мне кажется логичным, что OperationCanceledException может и сам шедулер кидать, вместо меня

Влад
18.06.2017
17:47:12
Проблемы с хостингом. ?

Ilya
18.06.2017
17:47:57
Это ничего не меняет
Как это не меняет?

Anton
18.06.2017
17:49:04
Всё равно же придётся ThrowIfCancellationRequested вызывать

Igor
18.06.2017
17:49:12
Проблемы с хостингом. ?
А был бы докер контейнер, смог бы менять хостинги на раз два. Деплой на чистый сервак за 1 минуту + 2 установка докера.

Ilya
18.06.2017
17:49:34
И сделать объект, в котором этот код написан idisposable и освобождать ресурсы в одном месте

Anton
18.06.2017
17:50:01
Вот так тогда будет: { try { var resource1 = await Load1(token); token.ThrowIfCancellationRequested(); var resource2 = await Load2(token); token.ThrowIfCancellationRequested(); var resource3 = await Load3(token); token.ThrowIfCancellationRequested(); } catch (OperationCanceledException) { if (resource1 != null) resource1.Dispose(); if (resource2 != null) resource2.Dispose(); if (resource3 != null) resource3.Dispose(); throw; } }

Ilya
18.06.2017
17:50:06
При ошибке и при окончании использования этого объекта

Google
Anton
18.06.2017
17:51:03
resource1?.Dispose()
Ну да, это мелочи

Ilya
18.06.2017
17:51:28
Третье не надо писать token.throw... сам метод бросит его

Anton
18.06.2017
17:51:29
Так прикол в том, что мне надо освободить ресурсы уже успешно завершившихся подтасков

Летучая
18.06.2017
17:51:30
HttpClient же принимает такие токены, как и многие другие таски из апи.

Например.

Anton
18.06.2017
17:53:05
Вызываю Dispose

Это вот то, что внутри catch

Ilya
18.06.2017
17:53:41
Дак на кой тебе их освобождать тут?

Anton
18.06.2017
17:54:00
А где?

Ilya
18.06.2017
17:54:28
В dispose методе объекта, где это код написан

Anton
18.06.2017
17:54:44
В общем вопрос то и не стоит, где их освобождать

Вопрос в том, как сделать, чтобы не проверять отмену после каждого шага

Летучая
18.06.2017
17:56:13
Вопрос в том, как сделать, чтобы не проверять отмену после каждого шага
Передавать токен внутрь тасков, которые хочешь проверять же

И уже внутри них чекать отмену

Страница 1268 из 1888

Эта группа больше не существует Эта группа больше не существует