[SOLVED] Чехарда в многопотоке

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
Всем привет!
Уже не первый день перелопачиваю форум, но так и не нашел внятного решения.

При работе в многопотоке (в данном случае 5 потоков) необходимо чтобы каждый поток брал один аккаунт из файла без дублирования - в файле 5 аккаунтов. Время работы каждого потока сильно варьируется.

Решение "1е действие - берешь и удаляешь акк, 2-е - записываешь в конец, 3-е - все остальное"
все равно приводит к тому, что в какой то момент аккаунты начинают повторяться. Получается лок в многопотоке не срабатывает.
Вариант с записью в БД мне кажется слишком громоздким.

Есть ли более изящное решение?
 

surrealmix

Client
Регистрация
07.03.2013
Сообщения
715
Благодарностей
409
Баллы
63

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
Это действие надо выполнять последним в шаблоне. Также вешать его на badend
А что если бэдэнд не сработает?
https://zennolab.com/discussion/threads/mnogopotok-kak-uznat-s-kakimi-akkauntami-rabotajut-drugie-potoki.40184/#post-299071
Логичен такой вариант, но что если комп зависнет, перезагрузится, работу зенки принудительно остановят?

Вот я сразу решил потестить этот вариант и в результате работа прекращена, а аккаунтов в файле -2
 
Последнее редактирование:

Geka1989

Client
Регистрация
17.12.2016
Сообщения
184
Благодарностей
23
Баллы
18
Всем привет!
Уже не первый день перелопачиваю форум, но так и не нашел внятного решения.

При работе в многопотоке (в данном случае 5 потоков) необходимо чтобы каждый поток брал один аккаунт из файла без дублирования - в файле 5 аккаунтов. Время работы каждого потока сильно варьируется.

Решение "1е действие - берешь и удаляешь акк, 2-е - записываешь в конец, 3-е - все остальное"
все равно приводит к тому, что в какой то момент аккаунты начинают повторяться. Получается лок в многопотоке не срабатывает.
Вариант с записью в БД мне кажется слишком громоздким.

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

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
Конечно повторяются, проходит шаб весь цикл и начинает снова с того что первым был, как вариант отработанные акки ложить в отдельный список, когда список с акками закончится, подгружать список заново и брать с удалением, так проблем точно не бует
Не пошел вариант с двумя списками - та же история. Обязательно один дублирующий лезет.
 

vrska

Client
Регистрация
07.02.2010
Сообщения
589
Благодарностей
408
Баллы
63

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
Это называется лень
А что делать, если и так работы очень много и не просто все успевать?
В БД не шарю, поэтому искал другие варианты.
Если вариантов нет, буду разбираться.

Варианты с 2мя списками - не помогли
Варианты с взял, записал, все остальное дальше - не помогли
Варианты с проверил, взял, поставил галку что занят, отработал галку убрал - не помогли
Варианты с бэкэндом - не помогли

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

vrska

Client
Регистрация
07.02.2010
Сообщения
589
Благодарностей
408
Баллы
63
  • Спасибо
Реакции: CAMOCBAJI

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8

doc

Client
Регистрация
30.03.2012
Сообщения
8 605
Благодарностей
4 596
Баллы
113

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
а что изменит бд?
Я не пробовал, возможно наладиться все))

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

doc

Client
Регистрация
30.03.2012
Сообщения
8 605
Благодарностей
4 596
Баллы
113
Я не пробовал, возможно наладиться все))

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

Но решит это только проблему внезапных ребутов. Если шаблон будет прерван - придётся вручную пересоздавать рабочий список.

Можно подумать в сторону того, чтобы каждой строке назначать время, после которого она будет доступна, но это много мороки и не факт, что такой подход будет приемлем
 
  • Спасибо
Реакции: CAMOCBAJI

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
При каждом запуске поток в локе проверяет, существует ли глобалка. Если не существует - значит первый запуск, и тогда очищаем основной список, заполняем его резервом, заполняем глобалку. Если существует - работаем как обычно с рабочим списком. Взяли строку с удалением в начале, положили обратно в конце.
Я нечто подобное пытался создать, но не пошло.
Теперь прояснилось многое, буду пробовать
Спасибо!
 

vrska

Client
Регистрация
07.02.2010
Сообщения
589
Благодарностей
408
Баллы
63
Сам использую такой снипет, взят с форума, переделан без знания C#
Работает хоть в 5, хоть 500 потоков без проблем.
Структура таблицы: id, username, status

// блокируем выполнение, чтобы другие потоки не испортили

lock(SyncObject) {
var result = String.Empty;
var command = new MySql.Data.MySqlClient.MySqlCommand();

//строка запроса, выбираем одну запись со статусом not_work
project.Variables["sql_query"].Value = "SELECT * FROM accounts WHERE status = 'not_work') LIMIT 1";
command.CommandText = project.Variables["sql_query"].Value.ToString();

//строка коннекта к бд
project.Variables["mysql_conn_string_c"].Value = "server=127.0.0.1;user=zenno;database=zenno_db;port=3306;password=zenno";
var connectionSTring = project.Variables["mysql_conn_string_c"].Value;

try {
command.Connection = new MySql.Data.MySqlClient.MySqlConnection(connectionSTring);
} catch(Exception e) {
result = "Mysql ошибка подключения";
}
if (result != String.Empty) {
return result;
}
try {
command.Connection.Open();
var read = command.ExecuteReader();
while (read.Read()) {

//читаем ответ, записываем в переменные
project.Variables["id"].Value = read["id"].ToString();
project.Variables["username"].Value = read["username"].ToString();
}
} catch(MySql.Data.MySqlClient.MySqlException e) {
result = "Mysql ошибка " + e.Message;
}
try {
command.Connection.Close();
command.Connection.Open();

//запрос смены статуса, устанавлием статус work
var query_lock_account = "UPDATE accounts SET status = 'work' WHERE id=" + Convert.ToInt32(project.Variables["id"].Value) + ";";
MySql.Data.MySqlClient.MySqlCommand com1 = new MySql.Data.MySqlClient.MySqlCommand(query_lock_account, command.Connection);
com1.ExecuteNonQuery();
} catch(MySql.Data.MySqlClient.MySqlException e) {
result = "Mysql ошибка " + e.Message;
} finally {
command.Connection.Close();
}
return result;
}
 
  • Спасибо
Реакции: CAMOCBAJI

CAMOCBAJI

Client
Регистрация
30.09.2011
Сообщения
34
Благодарностей
1
Баллы
8
Сам использую такой снипет, взят с форума, переделан без знания C#
Работает хоть в 5, хоть 500 потоков без проблем.
Структура таблицы: id, username, status

// блокируем выполнение, чтобы другие потоки не испортили

lock(SyncObject) {
var result = String.Empty;
var command = new MySql.Data.MySqlClient.MySqlCommand();

//строка запроса, выбираем одну запись со статусом not_work
project.Variables["sql_query"].Value = "SELECT * FROM accounts WHERE status = 'not_work') LIMIT 1";
command.CommandText = project.Variables["sql_query"].Value.ToString();

//строка коннекта к бд
project.Variables["mysql_conn_string_c"].Value = "server=127.0.0.1;user=zenno;database=zenno_db;port=3306;password=zenno";
var connectionSTring = project.Variables["mysql_conn_string_c"].Value;

try {
command.Connection = new MySql.Data.MySqlClient.MySqlConnection(connectionSTring);
} catch(Exception e) {
result = "Mysql ошибка подключения";
}
if (result != String.Empty) {
return result;
}
try {
command.Connection.Open();
var read = command.ExecuteReader();
while (read.Read()) {

//читаем ответ, записываем в переменные
project.Variables["id"].Value = read["id"].ToString();
project.Variables["username"].Value = read["username"].ToString();
}
} catch(MySql.Data.MySqlClient.MySqlException e) {
result = "Mysql ошибка " + e.Message;
}
try {
command.Connection.Close();
command.Connection.Open();

//запрос смены статуса, устанавлием статус work
var query_lock_account = "UPDATE accounts SET status = 'work' WHERE id=" + Convert.ToInt32(project.Variables["id"].Value) + ";";
MySql.Data.MySqlClient.MySqlCommand com1 = new MySql.Data.MySqlClient.MySqlCommand(query_lock_account, command.Connection);
com1.ExecuteNonQuery();
} catch(MySql.Data.MySqlClient.MySqlException e) {
result = "Mysql ошибка " + e.Message;
} finally {
command.Connection.Close();
}
return result;
}
Спасибо буду пробовать тоже
 

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