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

  • Автор темы Автор темы Mikhail B.
  • Дата начала Дата начала

Mikhail B.

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

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

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

а вообще правильно, надо их долбить, пусть делают. еще не хватает из коробки работы с мобильными проксями. а то все костыли, да костыли приходиться городить :)
 
Ну ты можешь решить эту задачу корректно? Тогда я сразу тему снесу и забудем про это!
вот именно что это просто задача. ну давай обсудим. что конкретно надо сделать ?
по описанию все размыто. есть работа по сбору инфы откуда - то, распределенная между N потоками. Как потоки не пересекаются, что бы не собирать одну и туже инфу, нам неизвестно. Сколько проходов они сделают нам то же не известно. Получается только один критерий это отсутствие работы этих самых шаблонов. ну довольно простая задача :)

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

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

Примерно по такой логике у меня и работают шабы. есть диспетчер, который анализирует расписание задач аккаунтов, сводит с временем перезагрузки мобильных проксей, смотрит сколько и какие аккаунты уже работают, и принимает решение о запуске новых потоков. и на примере моего случая, критерия окончания работы нет как класса.
 
Я бы сделал отдельный шаблон - диспетчер
Я не хочу делать отдельный шаблон, я хочу делать в этом. По ряду причин, которые не буду озвучивать. По этому дискуссия зашла в тупик. Если реально у тебя достаточно опыта и знаний сделать классное решение без дополнительных шаблонов. То давай обсудим. Но поверь там задача архисложная, ты уверен что хочешь тратить свое и мое время на обсуждение этого?
 
Я не хочу делать отдельный шаблон, я хочу делать в этом. По ряду причин, которые не буду озвучивать. По этому дискуссия зашла в тупик. Если реально у тебя достаточно опыта и знаний сделать классное решение без дополнительных шаблонов. То давай обсудим. Но поверь там задача архисложная, ты уверен что хочешь тратить свое и мое время на обсуждение этого?
ну если архисложная и дополнительных шаблонов нельзя... то конечно пусть разрабы голову ломают. :)
если получиться претендент, то можно будет и свои архисложные задачи попробовать переложить на них. :ce:
 
ну если архисложная и дополнительных шаблонов нельзя... то конечно пусть разрабы голову ломают.
Поверь я стараюсь сам решать, если не получается, я могу попросить опытных ребят на шарпе. Но эта задача действительно способна ломать мозг. Кстати мы давно еще обсуждали ее с @doc и он предложил вариант записи файлов и чека времени записи, какой-то замудренный способ который я к сожалению так и не проверил. Возможно настало его время))
 
Правильно ли я понял, что у тебя есть условные 100 потоков, которые одновременно выполняют задачу. В какой-то момент, один из потоков узнает, что все задания/страницы закончились и он последний. Это знает только этот один единственный поток.
И получается, что он должен дождаться завершения остальных потоков и после этого проделать какие-то действия, допустим, запустить синхронизацию/отправку данных?
 
Правильно ли я понял, что у тебя есть условные 100 потоков, которые одновременно выполняют задачу. В какой-то момент, один из потоков узнает, что все задания/страницы закончились и он последний. Это знает только этот один единственный поток.
И получается, что он должен дождаться завершения остальных потоков и после этого проделать какие-то действия, допустим, запустить синхронизацию/отправку данных?
Да. Но так же ему надо совершить действия и в начале.
А еще есть задача когда стоит 100 выполнений условно в 5 потоков, и один поток из всех 5 должен выполнить определенное действие, ну так же например записать в облако данные или что-то подобное.
 
У меня логика следующая, если поток знает, что он последний, то в этом случае, можно создать задачу ожидания, в try проверка состояния, а в finally проверяем завершение работы остальных потоков и далее выполняем, любой нужный нам код.
 
У меня логика следующая, если поток знает, что он последний, то в этом случае, можно создать задачу ожидания, в try проверка состояния, а в finally проверяем завершение работы остальных потоков и далее выполняем, любой нужный нам код.
Идея хорошая если надо в конце. Но если надо в начале, то уже не получится или если новые потоки подтягиваются, то тоже. по этому обращаемся к разработчикам за помощью))
 
Но если надо в начале
Если нужно в начале, то по идее, можно контролировать запуск и количество потоков на старте из шаблона. Как только совершили действие, накидываем потоки и задачи, они стартанут.
 
Если нужно в начале, то по идее, можно контролировать запуск и количество потоков на старте из шаблона. Как только совершили действие, накидываем потоки и задачи, они стартанут.
Ты имеешь ввиду нажать +1 выполнение и когда прошел нужный момент, то запускаются остальные?
Допустим, а как они поймут, что им не надо повторять за первым потоком, а пойти по альтернативной логике?
 
Типо такого не подойдёт?

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 Поправил косяк
 
Последнее редактирование:
а как они поймут, что им не надо повторять за первым потоком, а пойти по альтернативной логике?
Делаешь проверку, которую можно привязать к глобалке, файлу, базе данных и т.д.
Как только действие сделано, то передается кол-во потоков и кол-во заданий. Каждый последующий поток проверяет и пропускает эти действия.
 
Можно для этих целей сделать специальный список (далее буду называть его THREADS) с привязкой к файлу (что бы все потоки имели к нему доступ).
При старте каждого потока добавляем в него новую строку (содержимое не важно), по завершению работы потока - удаляем. Таким образом мы всегда из каждого потока знаем сколько сейчас работает потоков, оно равно кол-ву строк в списке THREADS.

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

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

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

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

Что бы сделать какое-то действие вконце, соцздаем кубик на выходе Good End
1) ставим лок (что бы только один поток в один момент времени выполнял этот участок кода)
2) удаляем строку из THREADS
2) проверяем кол-во строк в списке ... если = 0, то все потоки отработали и это последний => делаем что нужно
Хм. А ты смекалистый :D
 
нужно делать шаблон так что бы его не приходилось останавливать принудительно )))
Хахаха, зачем ты так пишешь. Теперь разрабы так и скажут. Мол делайте что бы не прерывать))
Да если не прерывать, то древний снипет ростоникса с этим справляется.
 
Когда главный поток выполнил свою задачу, он создает файл, и дает сигнал другим потокам начинать работу. Когда они начинают, то сверяют этот файл, и его наличие говорит о том, что можно идти так скажем направо. Если его нет, то значит поток является первым, он удаляет этот файл и выполняет вышеописанную логику.
Верно, мы создаем что-то, что может проверить каждый поток, это может быть файл, запись в файле, запись в базе данных, значение глобальной переменной. Что угодно, что можно проверить условием if.
И выполняем условие, только в случае true. Во всех остальных случаях, условие будет пропускаться.
Чтобы не городить, кучу кода, эти проверки ты можешь кидать в общий код и вызывать сразу от туда одной строкой. В общем коде, ты можешь класс прописать как bool, таким образом в if проверяешь сам класс, который будет вызываться условием.

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


ownBreak.png
 
Ты случаем не хочешь в конкурсе поучаствовать?))
Спасибо за предложение, думаю, что это все давно до меня придумано и написано на форуме. Разве что в текстовой версии конкурса, где можно изложить, почему лично я, делаю шаблоны условным подобным образом. Это может быть полезно, в большей степени, тем кто работает на кубиках. И то не уверен, что подобную статью пропустят, т.к. до этого были статьи по общему коду.
 
  • Спасибо
Реакции: Denchen
Верно, мы создаем что-то, что может проверить каждый поток, это может быть файл, запись в файле, запись в базе данных, значение глобальной переменной. Что угодно, что можно проверить условием if.
И выполняем условие, только в случае true. Во всех остальных случаях, условие будет пропускаться.
Чтобы не городить, кучу кода, эти проверки ты можешь кидать в общий код и вызывать сразу от туда одной строкой. В общем коде, ты можешь класс прописать как bool, таким образом в if проверяешь сам класс, который будет вызываться условием.


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


эта штука работает, когда прерывание происходит в каком-то с# цикле или ты смог прикрутить её вызов из любой точки шаба?
 
Спасибо за предложение, думаю, что это все давно до меня придумано и написано на форуме. Разве что в текстовой версии конкурса, где можно изложить, почему лично я, делаю шаблоны условным подобным образом. Это может быть полезно, в большей степени, тем кто работает на кубиках. И то не уверен, что подобную статью пропустят, т.к. до этого были статьи по общему коду.
Попробуй. Сотка на лк не лишняя, а то и больше.
Писать сюда 8-)
 
  • Спасибо
Реакции: RoyalBank
эта штука работает, когда прерывание происходит в каком-то с# цикле или ты смог прикрутить её вызов из любой точки шаба?
Тот код, что на скриншоте, я вызываю в начале каждого цикла. Если нужно из любой точки шаблона, то нужно переделать через создание задания на ожидание.
 
Тот код, что на скриншоте, я вызываю в начале каждого цикла. Если нужно из любой точки шаблона, то нужно переделать через создание задания на ожидание.
предположим, я обрываю шаб на каком-нибудь парсинге атрибута. Переделанный код сможет перехватить прерывание и проделать свои сохранения до того, как шаб оборвётся?
 
Последнее редактирование:
  • Спасибо
Реакции: Mikhail B.
Переделанный код сможет перехватить прерывание и проделать свои сохранения до того, как шаб оборвётся
Да. Все что нужно, это сделать обертку из задания с ожиданием, которая стартует в начале проекта. И как только условие прерывания выполняется, то мы уже вызываем дальше нужный класс, в котором прописываем все что нужно. И если необходимо делаем обертку из условий, которая будет принимать решение для тех или иных действий, исходя и того, где именно было прерывание. А чтобы получить условную точку прерывания, то мы создаем универсальную переменную и обновляем ее при вызове нужного класса в шаблоне, будь то парсинг/чтение/импорт/эспорт/синхронизация. Для каждого из этих этапов сможем предусмотреть необходимую модель поведения при прерывании.
 
Да. Все что нужно, это сделать обертку из задания с ожиданием, которая стартует в начале проекта. И как только условие прерывания выполняется, то мы уже вызываем дальше нужный класс, в котором прописываем все что нужно. И если необходимо делаем обертку из условий, которая будет принимать решение для тех или иных действий, исходя и того, где именно было прерывание. А чтобы получить условную точку прерывания, то мы создаем универсальную переменную и обновляем ее при вызове нужного класса в шаблоне, будь то парсинг/чтение/импорт/эспорт/синхронизация. Для каждого из этих этапов сможем предусмотреть необходимую модель поведения при прерывании.
Если ты правильно меня понял, то такая заготовка была бы тепло встречена на конкурсе. Многие бы хотели иметь возможность не терять данные из переменных при вынужденном прерывании шаблона. Такое вроде было в планах у самих разработчиков, вроде вызывать Bad_end при прерывании. Но я давно не отслеживал этот момент.
 
  • Спасибо
Реакции: Mikhail B.

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