В многопотоке поставить задачу исключительно одному потоку

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Куча костылей придумано, которые работают честно сказать так себе. Я использую счетчик глобалку которую необходимо обнулять в конце работы и то это подойдет не для всех ситуаций.

К примеру есть 100 потоков, мне надо в конце работы одним потоком импортировать полученные данные в облако. Как это сделать без костылей? Никак.

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

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 690
Баллы
113
эмммм.... а что так можно было ? ну переложить работу на разработчиков ? *HAHA*

а вообще правильно, надо их долбить, пусть делают. еще не хватает из коробки работы с мобильными проксями. а то все костыли, да костыли приходиться городить :-)
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113

Zhekaz

Client
Регистрация
14.03.2016
Сообщения
104
Благодарностей
55
Баллы
28

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 690
Баллы
113
Ну ты можешь решить эту задачу корректно? Тогда я сразу тему снесу и забудем про это!
вот именно что это просто задача. ну давай обсудим. что конкретно надо сделать ?
по описанию все размыто. есть работа по сбору инфы откуда - то, распределенная между N потоками. Как потоки не пересекаются, что бы не собирать одну и туже инфу, нам неизвестно. Сколько проходов они сделают нам то же не известно. Получается только один критерий это отсутствие работы этих самых шаблонов. ну довольно простая задача :-)

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

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

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

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Я бы сделал отдельный шаблон - диспетчер
Я не хочу делать отдельный шаблон, я хочу делать в этом. По ряду причин, которые не буду озвучивать. По этому дискуссия зашла в тупик. Если реально у тебя достаточно опыта и знаний сделать классное решение без дополнительных шаблонов. То давай обсудим. Но поверь там задача архисложная, ты уверен что хочешь тратить свое и мое время на обсуждение этого?
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 690
Баллы
113
Я не хочу делать отдельный шаблон, я хочу делать в этом. По ряду причин, которые не буду озвучивать. По этому дискуссия зашла в тупик. Если реально у тебя достаточно опыта и знаний сделать классное решение без дополнительных шаблонов. То давай обсудим. Но поверь там задача архисложная, ты уверен что хочешь тратить свое и мое время на обсуждение этого?
ну если архисложная и дополнительных шаблонов нельзя... то конечно пусть разрабы голову ломают. :-)
если получиться претендент, то можно будет и свои архисложные задачи попробовать переложить на них. :ce:
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
ну если архисложная и дополнительных шаблонов нельзя... то конечно пусть разрабы голову ломают.
Поверь я стараюсь сам решать, если не получается, я могу попросить опытных ребят на шарпе. Но эта задача действительно способна ломать мозг. Кстати мы давно еще обсуждали ее с @doc и он предложил вариант записи файлов и чека времени записи, какой-то замудренный способ который я к сожалению так и не проверил. Возможно настало его время))
 

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
Правильно ли я понял, что у тебя есть условные 100 потоков, которые одновременно выполняют задачу. В какой-то момент, один из потоков узнает, что все задания/страницы закончились и он последний. Это знает только этот один единственный поток.
И получается, что он должен дождаться завершения остальных потоков и после этого проделать какие-то действия, допустим, запустить синхронизацию/отправку данных?
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Правильно ли я понял, что у тебя есть условные 100 потоков, которые одновременно выполняют задачу. В какой-то момент, один из потоков узнает, что все задания/страницы закончились и он последний. Это знает только этот один единственный поток.
И получается, что он должен дождаться завершения остальных потоков и после этого проделать какие-то действия, допустим, запустить синхронизацию/отправку данных?
Да. Но так же ему надо совершить действия и в начале.
А еще есть задача когда стоит 100 выполнений условно в 5 потоков, и один поток из всех 5 должен выполнить определенное действие, ну так же например записать в облако данные или что-то подобное.
 

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
У меня логика следующая, если поток знает, что он последний, то в этом случае, можно создать задачу ожидания, в try проверка состояния, а в finally проверяем завершение работы остальных потоков и далее выполняем, любой нужный нам код.
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
У меня логика следующая, если поток знает, что он последний, то в этом случае, можно создать задачу ожидания, в try проверка состояния, а в finally проверяем завершение работы остальных потоков и далее выполняем, любой нужный нам код.
Идея хорошая если надо в конце. Но если надо в начале, то уже не получится или если новые потоки подтягиваются, то тоже. по этому обращаемся к разработчикам за помощью))
 

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
Но если надо в начале
Если нужно в начале, то по идее, можно контролировать запуск и количество потоков на старте из шаблона. Как только совершили действие, накидываем потоки и задачи, они стартанут.
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Если нужно в начале, то по идее, можно контролировать запуск и количество потоков на старте из шаблона. Как только совершили действие, накидываем потоки и задачи, они стартанут.
Ты имеешь ввиду нажать +1 выполнение и когда прошел нужный момент, то запускаются остальные?
Допустим, а как они поймут, что им не надо повторять за первым потоком, а пойти по альтернативной логике?
 

ebrwebrw

Client
Регистрация
20.08.2018
Сообщения
221
Благодарностей
163
Баллы
43
Типо такого не подойдёт?

C#:
//Допустим добавили шаб, 100 потоков, 100 выполнений
//Далее в конце шаблона  в Good End добавляем этот код

//название шаблона для проверки
string template_name = "Название_шаблона";//без .xmlz

bool isSendingData = false;
bool isFinish = false;

lock(SyncObject)
{
    //тут свой код для проверки выполнения задания
    //isFinish = false;
    //isFinish = true;
 
    //если задание выполненно(собрали необходимое колво данных/etc)
    if(isFinish)
    {
        var tasksList = ZennoPoster.TasksList;

        foreach (var task in tasksList)
        {
            string tname = Regex.Match(task,@"(?<=<Name>).*?(?=</Name>)").Value;
            if(tname == template_name)
            {
                //получаем колво повторений
                int tried = Convert.ToInt32(Regex.Match(task.ToString(),@"(?<=<NumberOfTries>).*?(?=</NumberOfTries>)").Value);
                project.SendInfoToLog("Количество выполнений: "+tried.ToString());
                if(tried ==1) isSendingData = true;
            }
        }
    }
    else
    {
        //задание не выполненно, добавляем +1 к "Сколько делать"
        ZennoPoster.AddTries(template_name,1);
    }

    //все данные собраны  и это последнее выполнение отправляем куда нужно
    if(isSendingData)
    {
        project.SendInfoToLog("Отсылаем данные");
        //Пишем отправку данных или на C#
        //Или задаем значение  переменной  и дальше на кубиках проверку переменной и действия в зависимости от её значения, либо завершаем шаблон либо отправляем данные куда необходимо
    }
}
Ну а если шаблон вышел по Bad End то ZennoPoster.AddTries("Название шаблона",1);

UPD Поправил косяк
 
Последнее редактирование:

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
а как они поймут, что им не надо повторять за первым потоком, а пойти по альтернативной логике?
Делаешь проверку, которую можно привязать к глобалке, файлу, базе данных и т.д.
Как только действие сделано, то передается кол-во потоков и кол-во заданий. Каждый последующий поток проверяет и пропускает эти действия.
 

WebBot

Client
Регистрация
04.04.2015
Сообщения
1 719
Благодарностей
1 377
Баллы
113
Можно для этих целей сделать специальный список (далее буду называть его THREADS) с привязкой к файлу (что бы все потоки имели к нему доступ).
При старте каждого потока добавляем в него новую строку (содержимое не важно), по завершению работы потока - удаляем. Таким образом мы всегда из каждого потока знаем сколько сейчас работает потоков, оно равно кол-ву строк в списке THREADS.

Что бы сделать какое-то действие вначале, создаем кубик вначале шаблона:
1) ставим лок (что бы только один поток в один момент времени выполнял этот участок кода)
2) проверяем кол-во строк в списке ... если = 0, то это первый поток => делаем что нужно и добавляем строку в THREADS, а если больше то ничего не делаем, а просто добавляем строку в THREADS

Что бы сделать какое-то действие вконце, соцздаем кубик на выходе Good End
1) ставим лок (что бы только один поток в один момент времени выполнял этот участок кода)
2) удаляем строку из THREADS
2) проверяем кол-во строк в списке ... если = 0, то все потоки отработали и это последний => делаем что нужно

Так же не забываем и в Bad End удалять строку (поток же завершается)
 
  • Спасибо
Реакции: Atlas

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Типо такого не подойдёт?
Не знаю, смотреть надо.

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

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
При старте каждого потока добавляем в него новую строку (содержимое не важно), по завершению работы потока - удаляем.
А если я работу прервал принудительно, то как он удалится?
Тут кстати опять надо обратится к разработчикам, что бы при прирывании ручном или по таймауту, BAD END все равно выполнялся. Тогда твоя логика имеет место быть.

Что бы сделать какое-то действие вконце, соцздаем кубик на выходе Good End
1) ставим лок (что бы только один поток в один момент времени выполнял этот участок кода)
2) удаляем строку из THREADS
2) проверяем кол-во строк в списке ... если = 0, то все потоки отработали и это последний => делаем что нужно
Хм. А ты смекалистый :D
 

WebBot

Client
Регистрация
04.04.2015
Сообщения
1 719
Благодарностей
1 377
Баллы
113

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
нужно делать шаблон так что бы его не приходилось останавливать принудительно )))
Хахаха, зачем ты так пишешь. Теперь разрабы так и скажут. Мол делайте что бы не прерывать))
Да если не прерывать, то древний снипет ростоникса с этим справляется.
 

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
Когда главный поток выполнил свою задачу, он создает файл, и дает сигнал другим потокам начинать работу. Когда они начинают, то сверяют этот файл, и его наличие говорит о том, что можно идти так скажем направо. Если его нет, то значит поток является первым, он удаляет этот файл и выполняет вышеописанную логику.
Верно, мы создаем что-то, что может проверить каждый поток, это может быть файл, запись в файле, запись в базе данных, значение глобальной переменной. Что угодно, что можно проверить условием if.
И выполняем условие, только в случае true. Во всех остальных случаях, условие будет пропускаться.
Чтобы не городить, кучу кода, эти проверки ты можешь кидать в общий код и вызывать сразу от туда одной строкой. В общем коде, ты можешь класс прописать как bool, таким образом в if проверяешь сам класс, который будет вызываться условием.

А если я работу прервал принудительно, то как он удалится?
У меня это реализовано двумя классами, первый проверяет на прерывание, во втором необходимые действия, очистка файлов, возврат строк в прокси и т.д. Можно и одним классом обойтись, но лично мне, так удобнее. Сам cycleBreaker кидаешь в начале всех циклов.


ownBreak.png
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
Ты случаем не хочешь в конкурсе поучаствовать?))
Спасибо за предложение, думаю, что это все давно до меня придумано и написано на форуме. Разве что в текстовой версии конкурса, где можно изложить, почему лично я, делаю шаблоны условным подобным образом. Это может быть полезно, в большей степени, тем кто работает на кубиках. И то не уверен, что подобную статью пропустят, т.к. до этого были статьи по общему коду.
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Верно, мы создаем что-то, что может проверить каждый поток, это может быть файл, запись в файле, запись в базе данных, значение глобальной переменной. Что угодно, что можно проверить условием if.
И выполняем условие, только в случае true. Во всех остальных случаях, условие будет пропускаться.
Чтобы не городить, кучу кода, эти проверки ты можешь кидать в общий код и вызывать сразу от туда одной строкой. В общем коде, ты можешь класс прописать как bool, таким образом в if проверяешь сам класс, который будет вызываться условием.


У меня это реализовано двумя классами, первый проверяет на прерывание, во втором необходимые действия, очистка файлов, возврат строк в прокси и т.д. Можно и одним классом обойтись, но лично мне, так удобнее. Сам cycleBreaker кидаешь в начале всех циклов.


эта штука работает, когда прерывание происходит в каком-то с# цикле или ты смог прикрутить её вызов из любой точки шаба?
 

Mikhail B.

Moderator
Регистрация
23.12.2014
Сообщения
14 328
Благодарностей
5 431
Баллы
113
Спасибо за предложение, думаю, что это все давно до меня придумано и написано на форуме. Разве что в текстовой версии конкурса, где можно изложить, почему лично я, делаю шаблоны условным подобным образом. Это может быть полезно, в большей степени, тем кто работает на кубиках. И то не уверен, что подобную статью пропустят, т.к. до этого были статьи по общему коду.
Попробуй. Сотка на лк не лишняя, а то и больше.
Писать сюда 8-)
 
  • Спасибо
Реакции: RoyalBank

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
эта штука работает, когда прерывание происходит в каком-то с# цикле или ты смог прикрутить её вызов из любой точки шаба?
Тот код, что на скриншоте, я вызываю в начале каждого цикла. Если нужно из любой точки шаблона, то нужно переделать через создание задания на ожидание.
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Тот код, что на скриншоте, я вызываю в начале каждого цикла. Если нужно из любой точки шаблона, то нужно переделать через создание задания на ожидание.
предположим, я обрываю шаб на каком-нибудь парсинге атрибута. Переделанный код сможет перехватить прерывание и проделать свои сохранения до того, как шаб оборвётся?
 
Последнее редактирование:
  • Спасибо
Реакции: Mikhail B.

RoyalBank

Client
Регистрация
07.09.2015
Сообщения
557
Благодарностей
547
Баллы
93
Переделанный код сможет перехватить прерывание и проделать свои сохранения до того, как шаб оборвётся
Да. Все что нужно, это сделать обертку из задания с ожиданием, которая стартует в начале проекта. И как только условие прерывания выполняется, то мы уже вызываем дальше нужный класс, в котором прописываем все что нужно. И если необходимо делаем обертку из условий, которая будет принимать решение для тех или иных действий, исходя и того, где именно было прерывание. А чтобы получить условную точку прерывания, то мы создаем универсальную переменную и обновляем ее при вызове нужного класса в шаблоне, будь то парсинг/чтение/импорт/эспорт/синхронизация. Для каждого из этих этапов сможем предусмотреть необходимую модель поведения при прерывании.
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 607
Благодарностей
4 598
Баллы
113
Да. Все что нужно, это сделать обертку из задания с ожиданием, которая стартует в начале проекта. И как только условие прерывания выполняется, то мы уже вызываем дальше нужный класс, в котором прописываем все что нужно. И если необходимо делаем обертку из условий, которая будет принимать решение для тех или иных действий, исходя и того, где именно было прерывание. А чтобы получить условную точку прерывания, то мы создаем универсальную переменную и обновляем ее при вызове нужного класса в шаблоне, будь то парсинг/чтение/импорт/эспорт/синхронизация. Для каждого из этих этапов сможем предусмотреть необходимую модель поведения при прерывании.
Если ты правильно меня понял, то такая заготовка была бы тепло встречена на конкурсе. Многие бы хотели иметь возможность не терять данные из переменных при вынужденном прерывании шаблона. Такое вроде было в планах у самих разработчиков, вроде вызывать Bad_end при прерывании. Но я давно не отслеживал этот момент.
 
  • Спасибо
Реакции: Mikhail B.

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)