Многопоточное использование ресурсов-текстовых файлов как списков



  • Есть текстовый файл, он подгружается как ресурс.
    Можно ли как-то при использовании пяти потоков, например, разбить его на 5 примерно равных списков, чтобы каждый поток обрабатывал свой список строк?

    Наверняка это очень замороченное решение, поэтому объясняю, зачем это нужно:
    Нужно принимать по 3 смски (вместо одной как обычно) -- активировать 3 аккаунта на каждый номер сервисов активации. Соответственно, где-то надо хранить айди номера и количество активаций, сделанное на каждый номер.

    Решил не заморачиваться с хранением этого всего в глобальных переменных и хранить эту информацию в обычной переменной (потому что если хранить это глобально, то потоки будут "бороться" за прием смс на каждый номер и тогда надо будет хранить еще статус номера -- свободен он или ожидает смс.
    Тогда у меня будет просто по одному номеру на каждый поток, который после 3х активаций будет меняться. Понятное дело, что если аккаунтов 10, то 3 номера будут использованы по 3 раза, а один номер -- всего лишь один раз, т.е. немного денег я все-таки "потеряю", но на больших объемах эти потери не важны.

    Если есть более оптимальное решение -- буду благодарен за подсказку:)



  • @yo
    Насколько я вас понял - какой-то сервис поддерживает до 3 регистраций с одного номера и нужно использовать номера по максимуму.
    Опять же, насколько я понял вопрос, достаточно выставить макс количество успешных использований на ресурс с номерами в 3 и установить галку "Запись", чтобы строки удалялись из файла.
    http://prnt.sc/cl1pct



  • Спасибо за оперативный ответ!
    Да, все верно.
    Тогда еще один вопрос:
    как хранить количество активаций вместе с номером?
    То, что они сами удалятся я понял, но у сервиса (sms-activate) разные запросы для первой активации и повторной.



  • @yo Либо файл, который строки вида номер:количество использований.
    Либо множество файлов с именем таким, как номер и содержанием - количеством использований.

    Если не нужно запоминать информацию между запусками проекта - достаточно хранить список в глобальной переменной.



  • Понял, спасибо!



  • Для работы с файлами какие надо галки ставить возле greedy algorithm и ниже?
    Учитывая, что файлы будут создаваться, изменяться и удаляться?

    И количество использований (успешных/неуспешных) надо по максимуму ставить?
    И интервал между использованиями какой?

    Короче нужен полный скриншот настроек ресурса:)

    UPD:
    Попытался поработать с файлами сам и понял, что я вообще ничего не понимаю.
    Буду дико благодарен за пример проекта с многопоточной работой с созданием/чтением/изменением/удалением файлов



  • @yo Если задача состоит в том, чтобы сохранять какие-то дополнительные параметры для номеров телефона, то лучше вообще обойтись без ресурсов.
    Допустим, нужно установить количество использований для заданного телефона в 0 - создаем файл действием "Запись В Файл"
    0_1474587604239_WritePhoneToFile.png

    Нужно получить количество использований для данного телефона по номеру - читаем файл с заданным номером в переменную действием "Читать Файл"
    0_1474587827419_ReadPhoneToFile.png



  • Проблем с мнопоточностью при таком подходе разве не будет?
    Может же случиться так, что два потока одновременно обратятся к файлу.

    (задача в итоге была решена с помощью работы с несколькими аккаунтами в одном потоке и использовании нескольких переменных для хранения переменных номера и количества активаций)



  • @yo

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

    Нет, не будет. В БАС есть 2 типа действия - синхронные и асинхронные. Синхронные выполняются в одном потоке. Среди асинхронных - работа с браузером, хттп клиентом, работа с ресурсами, поиск файлов. Установка переменных, запись и чтение файлов - синхронные.

    (задача в итоге была решена с помощью работы с несколькими аккаунтами в одном потоке и использовании нескольких переменных для хранения переменных номера и количества активаций)

    Рад, что удалось решить проблему.



  • @support у меня сейчас есть схожая задача по сути. Перечитал этот топик, но решения (элегантного) так и не узрел )

    нужно синхронное, блокируемое (lock) действие взять строку из списка (пусть просто глобальная переменная с массивом). А еще лучше возможность заблокировать глобальную видимость (всех глобальный переменных) и пока этот блок действует, то все остальные потоки будут покорно ожидать ее разблокировки, чтобы они могли с нее считать/записать.
    Т.е. поток 1 собирается что-то сделать с global var, он сперва вешает замок на эту global var или вообще на всю global area и после этого начинает что-то там делать с ней, читать/писать. В этот период другие потоки , когда доходят до какого-то действия с global var, перед его выполнением, они проверяют не висит ли на ней блокировка, если висит, то ждут пока не разблокируется.
    это пример с глобальной переменной, но мне это не важно, пусть будет любой способ хранить инфу, пусть файл..

    Попытаюсь очень ясно описать задачу:

    1. Запускаю 10 потоков. Каждый из них начал выполнять свои дела, дошел до момента, где получил извне (с веба) строку st1. В итоге у каждого потока есть по одной своей уникальной строке, полученной из веба.
    2. дальше когда с этой строкой выполнены нужные операции , к ней добавляется приставка :1 т.е. st1:1
    3. теперь нужно не забыть/выкинуть эту строку, а отдать ее другим потокам (точнее одному)
    4. другой поток должен взять эту строку (перебрать целый список таких строк, т.к. многопоток, строк будет много) и найти там строку с вторым параметром :1
      !!! чтобы во время этого поиска другие потоки не искали, иначе несколько потоков найдут себе одинаковую строку , а это не нужно. (теперь понятно, описание выше, о какой блокировке(lock) шла речь)
      Когда поток нашел подходящую строку, то он ее берет из списка с удалением, чтобы, когда пойдут другие потоки искать себе строки (после разблокировки) , они не взяли уже взятые другими потоками.
      Ну вот все, думаю суть описал, вопрос то, каким из способов можно такое решить в БАС?
      Если бы можно было блокировать глобальные переменные, то задача решилась бы без проблем. Опять же, блокировка нужна синхронная. Мы себе спокойно заблочили global var, прошлись по ее содержимому , нашли нужное, удалили его после взятия, дальше разблокировали global var, чтобы другие потоки могли получить себе свою инфу.

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

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

    Не хватает простого механизма: создать список (!!! доступный всем потокам) , взять от туда строку с удалением, чтобы не досталось нескольким потокам по одинаковой строке. + Добавить строку в конец, чтобы дальнейшие потоки, могли ее получить в процессе работа.

    Уж прости, что дохера текста ) Но зато суть задачи описаны с разных сторон , вроде.

    зы: что-то мне сдается, что все описанное выше можно решить вот этим
    alt text
    в OnAppStart указать создание ресурса с приблизительно такими параметрами:
    alt text

    Что значит "ждать появления" ? Это наверное, если ресурс пуст, то действие взятия строки с ресурса будет ждать, пока там что-то не появится. Но для меня вариант не подходит, т.к. если ресурс пуст, то нужно пойти дальше и получить нужные данные с веба. Значит эту опцию не включаем.

    Дальше брать из ресурса строку так:
    alt text
    Обернуть взятие из ресурса строки в Игнор ошибок (на случай, если ресурс пуст).
    Дальше уже по статусу ошибки, решать брать данные с веба или нет.

    После взятия вызывать "Удалить Текущий Элемент".



  • @out

    В БАС есть 2 фичи:

    1. Во время выполнения синхронных операций выполняется только один поток и управление не может быть передано в другой, пока не будет вызвана асинхронная.
    2. Работа с глобальными переменными, работа со списками, циклы являются синхронными(но не получение ресурсов).

    Грубо говоря, если в коде нет функции, которая заканчивается на ! sleep(1000)! load("google.com")! и т. д., то она синхронная.

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

    Вот пример - такой код всегда будет выводить 0, если бы правило 1). не работало, он бы выводил не 0 значение.

    testglobalvars.xml

    Еще в будущем будет действие "Блокировка Потока" такое как игнорировать ошибки, только оно позволит блокировать кусок кода в котором есть асинхронные функции.



  • @support said in Многопоточное использование ресурсов-текстовых файлов как списков:

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

    меня вот что беспокоило:

    • работает 100 потоков
    • поток 1 получил значение с глобальной переменной
      -- опасная зона , идут остальные действия, не касающиеся глобальной пер.
    • поток 1 начал это значение распарсивать / проверять / выбирать не важно что, он работает с этим значением, которое сейчас находится в локальной переменной.
    • после того , как поток 1 взял что ему нужно и это удалил с этих значений, он записывать в глобальную уже измененный данные.

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



  • @out said in Многопоточное использование ресурсов-текстовых файлов как списков:

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

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



  • @support очень гуд, спасибо! Теперь все прояснилось. Эти посты надо в закладки добавить )



  • @out А еще лучше тему в вики дополнить про многопоточность. Но хочу добить фреймы сначала.



  • @out said in Многопоточное использование ресурсов-текстовых файлов как списков:

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

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

    @support said in Многопоточное использование ресурсов-текстовых файлов как списков:

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

    Ведь чтение/запись в файл синхронные (ты вроде это писал где-то).



  • @out Да, операции с файлами тоже синхронные.



  • @out Исключение - поиск файлов, он асинхронный. Также хочу обратить внимание, что получение ресурсов тоже асинхронная операция. Так что ресурсы нужно сохранять в переменные до критической секции.



  • А выведение в лог и ожидание ("спать") - синхронные или асинхронные? Есть где-то инфа с делением всех действий на синхронные и асинхронные?



  • @Antonio said in Многопоточное использование ресурсов-текстовых файлов как списков:

    А выведение в лог и ожидание ("спать") - синхронные или асинхронные?

    Добавь эти действия, и открой вкладку Скрипт, если код действия будет заканчиваться на ! то оно асинхронное.


Log in to reply