Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418

Выполнить только последнюю вызванную функцию

12.04.2022, 06:53. Показов 2188. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня есть асинхронная функция FooAsync(object current), которая выполняет большую работу по обработке аргумента. Я хочу, чтобы пользователь мог запустив второй раз эту функцию прервать выполнение предыдущей задачи и начать заново с другим аргументом асинхронно. Как это можно сделать? Я пытался это осуществить с помощью статического CancellationToken в классе, где лежит функция FooAsync, но это не сработало (
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.04.2022, 06:53
Ответы с готовыми решениями:

Как только один раз выполнить функцию в данном проекте?
(SFML)Нужно выполнить view.zoom(0.9f); при вызове fight, но перед самой функцией, а у меня вызывается постоянно в Update, как это...

Как дождаться полного выполнения функции и только тогда выполнить другую функцию?
Не получается дождатся полного выполнения первой функции. Наведите пример с async,await и с Promise

Как определить загрузку всех 100% картинок и только потом выполнить функцию?
$.post('./Controllers/Index/Resize', {src: img.src}, (function (data) { $('#wallimages').remove(); ...

32
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
14.04.2022, 13:49
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Aycon Посмотреть сообщение
Lock не принимает токен отмены в качестве параметра
lock нужен ссылочный тип.
Но зачем вам токен в параметрах передавать?
У вас же был статический семафор - его эквивалентом (в этом случае) будет lock со статическим локером.

Может.
В моём примере нет лага между получением токена и выходом из синхронизации.
В принципе тоже самое можно сделать и в вашем коде, но сам семафор в нём не пойму зачем нужен и ветка исключения запустит задачу с не пойми каким токеном:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static SemaphoreSlim _semaphore = new Semaphore(1, 1);
private static CancellationTokenSource _cancellSource = new CancellationSource();
public static async Task<TEntity> ConvertToLastCallAsync<TEntity>(Func<CancellationToken, Task<TEntity> func, CancellationToken token)
{
    CancellationToken _token = _cancellSource.Token;
    await _semaphore.WaitAsync(token);
    try
    {
        _cancellSource.Cancel();
        _cancellSource.Dispose();
        _cancellSource = new CancellationSource();
        _token = _cancellSource.Token;
    }
    finally
    {
        _semaphore.Release();
    }
 
    return await func.Invoke(_token);
}
Добавлено через 7 минут
Aycon, может вы подобное имели ввиду:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static SemaphoreSlim _semaphore = new Semaphore(1, 1);
private static CancellationTokenSource _cancellSource = new CancellationSource();
public static async Task<TEntity> ConvertToLastCallAsync<TEntity>(Func<CancellationToken, Task<TEntity> func, CancellationToken token)
{
    TEntity rez = default;
    await _semaphore.WaitAsync(token);
    try
    {
        _cancellSource.Cancel();
        _cancellSource.Dispose();
        _cancellSource = new CancellationSource();
        rez = await func.Invoke(_cancellSource.Token);
    }
    finally
    {
        _semaphore.Release();
    }
 
    return rez;
}
Добавлено через 3 минуты
Aycon, то есть, если у вас есть try, то как-то надо обрабатывать и catch - иначе какой в нём смысл?

Но я не пойма, что в вашем коде работы с _cancellSource может создать исключение?
Для чего вы, вообще try поставили?
Только если _cancellSource будет null, но по логике вашей реализации - это невозможная ситуация.

Добавлено через 5 минут
Ну, разве что между Dispose() и созданием нового, другой поток вызовет Cancel();.
Хотя это вероятность 1 на триллион или даже менее.
Но в этом случае вы получите результат противоположный нужному вам.
Метод вызывающий Cancel(); и поймавший исключение, начинает свою работу позже вызывающего Dispose().
И, следовательно, у вас "отвалится" метод с актуальными данными, а не с устаревшими.

Добавлено через 2 минуты
По факту из вашего кода можно полностью удалить try и ничего не изменится.
0
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
14.04.2022, 13:50  [ТС]
Элд Хасп, да, я бы хотел чтобы я так написал и оно так и работало, но в этом случае второй вызов функции будет ожидать завершения первого вызова (ненужные 10 минут обработки неактуального объекта) а потом ещё 10 мин будет считать сама.

Добавлено через 32 секунды
Элд Хасп, и я не понимаю о каком лаге вы говорите. Что за лаг?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
14.04.2022, 13:53
Aycon, сделайте с локером как в моём примере и периодической проверкой токена в методе func.
И всё будет работать как надо.
1
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
14.04.2022, 13:53  [ТС]
Элд Хасп,
Для чего вы, вообще try поставили?
чтобы освободить семафор в финализаторе. Я не знаю, будет ли это SemaphoreSlim или туда передадут его потомка с ошибкой в диспоус
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
14.04.2022, 13:57
Цитата Сообщение от Aycon Посмотреть сообщение
и я не понимаю о каком лаге вы говорите. Что за лаг?
Если имеете ввиду предыдущее сообщение, то лаг между вызовами Cancel(); и Dispose().
Что ещё может вызвать исключение в вашем коде - я не знаю.
Вы же для чего то же ставили try - больше ни для чего он там не может быть нужен.

Добавлено через 1 минуту
Цитата Сообщение от Aycon Посмотреть сообщение
чтобы освободить семафор в финализаторе. Я не знаю, будет ли это SemaphoreSlim или туда передадут его потомка с ошибкой в диспоус
Если в работе с семафором будет ошибка, то она возникнет в строке await _semaphore.WaitAsync(token);.
А у вас эта строка не охвачена try.
1
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
14.04.2022, 14:18  [ТС]
Элд Хасп, Зачем? Чтобы что, остановить func тогда как я хотел остановить ConvertToLastCallAsync? Кроме того, это запах кода. Лишняя нагрузка на процессор, лучше уж использовать CancellationTokenSource.CreateLinkedToTo kenSource, если это нужно. Я специально стараюсь написать архитектуру без опроса по таймеру и ожидания. В Delay опрос по таймеру просто неизбежен.

Добавлено через 8 минут
Элд Хасп,
Если в работе с семафором будет ошибка, то она возникнет в строке
прошу прощения, оговорился. В _cancellSource конечно же. Это незапечатаный класс. А вообще, я использовал try finally по рекомендации msdn и по привычке.

Добавлено через 6 минут
Элд Хасп, а с чем связан лаг? У меня нет задержки

Добавлено через 3 минуты
Элд Хасп, аа, релиз.... я не обратил внимание. Так действительно быстрее
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
14.04.2022, 14:27
Цитата Сообщение от Aycon Посмотреть сообщение
а с чем связан лаг? У меня нет задержки
С тем что это не атомарные операции и между таковыми всегда присутствует лаг.

Цитата Сообщение от Aycon Посмотреть сообщение
оговорился. В _cancellSource конечно же
Если не опасаетесь этого лага, то чего вообще ловит ваш try?
На какой строке в нём, по вашему мнению, может произойти исключение?

Цитата Сообщение от Aycon Посмотреть сообщение
Чтобы что, остановить func тогда как я хотел остановить ConvertToLastCallAsync
Остановить func токеном вы можете либо перед началом выполнения задачи.
Либо периодической "ручной" проверкой токена в методе выполняемом задачей.
Других вариантов нет.

Для исключения коллизий при отмене токена и его пересоздании (очень маловероятных, но всё же), блок кода который это делает должен быть синхронизирован.
Что тут делает семафор.....
Мне даже в голову не приходит.
Он ограничивает количество потоков.
А вам нужно синхронизация работы с токеном.
Одно с другим, на мой взгляд, вообще, никак не связано.
0
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
14.04.2022, 14:41  [ТС]
Элд Хасп, хочу поведение как на нижней половине картинки. Только вместо потоков контексты синхронизации и чтобы это было потокобезопасно и чтобы вызываемая функция была асинхронной и чтобы она сама себя прерывала, либо её обёртка как в моём случае. И чтобы без блокирующих ожиданий и чтобы без опросов по таймеру. (Это ужасно, ну правда, есть же коллбеки, токен отмены, observer в конце концов).
Миниатюры
Выполнить только последнюю вызванную функцию  
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
14.04.2022, 18:35
Лучший ответ Сообщение было отмечено Aycon как решение

Решение

Цитата Сообщение от Aycon Посмотреть сообщение
Только вместо потоков контексты синхронизации
???
Как это?
Контекст синхронизации связан с конкретным потоком.
Не бывает Контекста синхронизации без потока.

Цитата Сообщение от Aycon Посмотреть сообщение
и чтобы это было потокобезопасно
В общем виде это не обеспечишь.
Только если всё делать в одном потоке.
А так зависит от используемых объектов и способов работы с ним.

Цитата Сообщение от Aycon Посмотреть сообщение
и чтобы вызываемая функция была асинхронной
В каком смысле ассинхронной?
Если async-await, то она будет выполняться на пуле потоков.
Но вы пишите за Контексты синхронизации.....
У меня в голове не складывается понимание того, что вы хотите сделать.

Цитата Сообщение от Aycon Посмотреть сообщение
чтобы она сама себя прерывала, либо её обёртка как в моём случае
Задачу (Task) прервать нельзя - она может только сама завершится.
Можно прервать поток в котором выполняется задача (Thread.Abort()), но это плохая идея.
С возможными потенциальными багами и влиянием на другие задачи.

В вашем случае я не понимаю почему вы считает, что достигли такого результат.
Обёртка здесь точно не причём.
Или задача func в своём теле имеет блок проверки условий и отмены себя, или никто начавшую исполняться задачу не отменит.

Цитата Сообщение от Aycon Посмотреть сообщение
И чтобы без блокирующих ожиданий и чтобы без опросов по таймеру
Если вам нужна синхронизация, то блокирующие ожидания будут в любом случае.
По другому обеспечить потокобезопасность объекта невозможно.
Пока один метод с ним работает, другой не может с ним работать.
Если это сделано на локерах, то исполняющая и ожидающие задачи могут быть из разных потоков.
Если вы запускаете все задачи через Контекст синхронизации в одном потоке, то локеры не нужны, но это не значит что не будет ожидания.
Просто все методы будет выполнять один поток.
И пока текущий метод выполняется - остальные ждут в очереди задач этого потока (веренее Контекста синхронизации).
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
15.04.2022, 14:42
Aycon, может небольшую долю неясности для вас внесло то, что вы эмулировали реальный метод с помощью Task.Delay(...):
Цитата Сообщение от Aycon Посмотреть сообщение
в fooAsync лежит Task.Delay(2000, token) и try catch finally выводы в консоль для отладки.
С точки зрения работы с потоками такая эмуляция длительного метода неверна.
Такой метод на время своего исполнения не освобождает поток, а Task.Delay - освобождает.
Поэтому правильно эмулировать длительный метод будет методом Thread.Sleep(...).
0
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
15.04.2022, 14:46  [ТС]
Элд Хасп, в этом то и дело, что метод Должен освобождать поток. Те обработка происходит в другом потоке, чтобы не занимать ui
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16157 / 11277 / 2891
Регистрация: 21.04.2018
Сообщений: 33,163
Записей в блоге: 2
15.04.2022, 15:00
Цитата Сообщение от Aycon Посмотреть сообщение
что метод Должен освобождать поток. Те обработка происходит в другом потоке, чтобы не занимать ui
Не путайте поток вызвавший асинхронный метод и поток его исполняющий.
Вызывавший поток будет освобождён в любом случае, но с Delay() будет освобождаться и исполняющий поток, что не верно сточки зрения эмуляции длительного метода.
Не забывайте сам по себе длительный вычислительный метод является синхронным.
Никакой асинхронности в нём нет.
Асинхронность появляется тогда когда его заворачивают в задачу.
А Delay, в принципе, не может быть синхронным, поэтому он не может верно эмулировать длительный вычислительный метод.

Добавлено через 4 минуты
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
// Длительный метод
private void LongMethod()
{
    // Эмуляция задержки исполнения
    Thread.Sleep(5000); // Delay здесь просто не получится вставить
}
 
// Асинхронная оболочка для него
publiс async Task LongMethodAsync()
{
    await Task.Run(LongMethod);
    // Здесь можно вставить Delay, но это не будет эквивалентом работы метода LongMethod
}
0
13 / 11 / 2
Регистрация: 07.05.2015
Сообщений: 418
16.04.2022, 16:54  [ТС]
Элд Хасп, спасибо, буду иметь в виду
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.04.2022, 16:54

Выполнить последнюю фигуру, зная как формируется начальная
Выполнить последнюю фигуру, зная как формируется начальная (ваще нуль в рисунках:((()

Как использовать переменную php вызванную Ajax-ом?
Здравствуйте дорогие форумчане! Сложилась такая проблемка. При нажатии на кнопку отправляется ajax запрос которая содержит значение id в...

Добавление своего текста в форму вызванную из Iframe
Здравствуйте все. Не могу найти решение задачи Есть страница, в которой встроен Iframe. В нем загружается страница каталога. При выборе...

Как исправить ошибку загрузочного сектора вызванную вирусом
Загрузился с CD, прогнал антивирусники CureIt, AVZ и другое. Ничего не помогает. При загрузке выдает синий экран и ругается на ошибки...

открывает только последнюю страницу
require_once($_SERVER.'/auth.php'); require_once($_SERVER.'/news.php'); открывает только последнюю страницу, как исправить?


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

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Запрет пометки на удаление и отмены проведения
Maks 16.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "ПутевойЛист" разработанного в КА2. Задача: запретить помечать на удаление и отменять проведения путевого листа при условии, если он сдан. . .
Как надо было делать правильно - вообще не слушать ИИ, его дело - текст.
Hrethgir 15.07.2026
А вообще надо было делать не так, чтобы не исправлять ошибку https:/ / www. cyberforum. ru/ blogs/ 223907/ 10996. html , правильно было : удалил кнопку, а потом добавил её. Всё это стресс конечно. Почему?. . .
Знаете, от чего появляется стресс?
kumehtar 15.07.2026
Стресс появляется оттого, что вы, зная как поступить правильно, делаете наоборот. Ларри Уингет
Нас бьют, а мы крепчаем? Какая чушь!
kumehtar 15.07.2026
Вот это вот бытующее мнение, что человек меняется только под действием проблем, всегда считал вредоносным. Поверь, от проблем у людей появляются не изменения, а нервное расстройство и ПТСР. А. . .
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru