Особенности использования стандартных lock'ов для многопотока

Данная переменная своя для каждого шаблона и не подходит для блокировки.
Для шаблонов-то ясно, что разные, речь о потоках одного шаблона была, но, думаю, что ты просто не дописал.
Там проблема больше, возвращаемый объект списка разный у шаблонов.
Так всё-таки, у шаблонов или потоков одного шаблона?
Для себя уже разобрался каким образом блокировать доступ к критической секции и каким объектом.
да он не понимает. я ему написал вон выше что локальные переменные не подходят для лока многопотока, в ответ только тролинг получил.
Твоё сообщение:
Phoenix78 написал(а):
лочить локальную переменную не самая лучшая идея для работы в многопотоке
Формулируй чётче.

P.S. Тему поднял потому что комментарии к статье внесли путаницу.
Подытожу.
LaGir прав в своей статье!
То, что обсуждали в комментариях, про блокировку доступа к Зенносписку самим Зенносписком неверная информация и блокировка не работает, так делать нельзя.
 
потоки одного шаблона, совершенно ничем не отличаются от потоков других шаблонов. для каждого потока создается свое уникальное пространство, которое не пересекается никак с другими потоками, кроме специально выделенных мест, обозначенных static . вот эти статические места и можно залочить в многопотоке, так как они являются общими для всех потоков.
но я же не гуру c# , поэтому хз, как оно на самом деле *HAHA*
 
но я же не гуру c#
Да понял, понял, не повторяйся :D
потоки одного шаблона, совершенно ничем не отличаются от потоков других шаблонов
Ну и что ты опять пишешь?
Статическим объектом, не вынесенным в общую библиотеку для шаблонов или объектом не инициализированным общей глобальной переменной, ты никак не залочишь доступ к критической секции другого шаблона.

Мне и так было понятно, что это не работает, вопрос почему, для себя разобрался, спасибо за помощь техподдержке Зеннолаба и ZSharp!
 
Лок почему-то не работает, может я что то неправильно делаю.
Делаю парсинг по объявлениям в 30 до 50 потоков
Ошибка возникает, когда удаляю дубли, пробовал два разных лока
C#:
Развернуть Свернуть Копировать
lock(Locker.Ссылки){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var lst = project.Lists["Ссылки"];
var buff = lst.Distinct().ToList();
lst.Clear();
lst.AddRange(buff);
}

C#:
Развернуть Свернуть Копировать
lock (SyncObjects.ListSyncer){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var lst = project.Lists["Ссылки"];
var buff = lst.Distinct().ToList();
lst.Clear();
lst.AddRange(buff);
}
1622361624252.png
Подскажите что делать надо
 
Лок почему-то не работает, может я что то неправильно делаю.
Делаю парсинг по объявлениям в 30 до 50 потоков
Ошибка возникает, когда удаляю дубли, пробовал два разных лока
C#:
Развернуть Свернуть Копировать
lock(Locker.Ссылки){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var lst = project.Lists["Ссылки"];
var buff = lst.Distinct().ToList();
lst.Clear();
lst.AddRange(buff);
}

C#:
Развернуть Свернуть Копировать
lock (SyncObjects.ListSyncer){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var lst = project.Lists["Ссылки"];
var buff = lst.Distinct().ToList();
lst.Clear();
lst.AddRange(buff);
}

Подскажите что делать надо
непонятно зачем lst нужна. у тебя же list уже есть. работай только с ней.
 
  • Спасибо
Реакции: Roman48
непонятно зачем lst нужна. у тебя же list уже есть. работай только с ней.
Я нашел сниппет для удаления дублей, и нашел сниппет для привязки к файлу, и сложил.
Теперь я понял, надо удалить
var lst = project.Lists["Ссылки"];
 
Я нашел сниппет для удаления дублей, и нашел сниппет для привязки к файлу, и сложил.
Теперь я понял, надо удалить
var lst = project.Lists["Ссылки"];
ну как то так. попробуй, будут ли ошибки.
C#:
Развернуть Свернуть Копировать
lock (SyncObjects.ListSyncer){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var buff = list.Distinct().ToList();
list.Clear();
list.AddRange(buff);
}
 
  • Спасибо
Реакции: Roman48
ну как то так. попробуй, будут ли ошибки.
C#:
Развернуть Свернуть Копировать
lock (SyncObjects.ListSyncer){
// Привязать список к файлу
IZennoList list = project.Lists["Ссылки"];
list.Bind(@project.Variables["link_a"].Value);
var buff = list.Distinct().ToList();
list.Clear();
list.AddRange(buff);
}
1622363339894.png
 
Другой сниппет нашел и нет ошибок, всегда помогает если испробывать несколько вариантов
C#:
Развернуть Свернуть Копировать
lock(Locker.Ссылки){
// Привязать список к файлу
string path = project.Variables["link_a"].Value;
var lines = System.IO.File.ReadAllLines(path).ToList().Distinct().ToList();;
System.IO.File.WriteAllText(path, string.Join(Environment.NewLine, lines));
return 0;
}
 
что то не то. я попробовал щас в 100 потоков запустить. и нормально, ошибок нет.
Но я же их не сам нарисовал. Там одно временно три работы с этим списком, и все на много потоках
 
Но я же их не сам нарисовал. Там одно временно три работы с этим списком, и все на много потоках
у тебя там код ошибки, куда ведет ? а других местах обращение к списку идет через c# код ?
 
у тебя там код ошибки, куда ведет ? а других местах обращение к списку идет через c# код ?
Привязывал через списки так, может это и есть косяк? сейчас попробую все переделать
1622368957747.png
 
Именно в этом и была проблема, сейчас 50 потоков и не одной ошибки, я привязывал для того чтобы файл создать, теперь сделаю проверку на существования файла и все
 
  • Спасибо
Реакции: Koqpe
Можете подсказать в чем вопрос? Написал в ветке "вопросы новичков" - тема "отложенный запуск потоков" ?
 
Для популярных типов внешних ресурсов в ZennoPoster предусмотрено три объекта синхронизации, которые в C#-коде указываются в круглых скобках после lock:
SyncObjects.ListSyncer - для списков
SyncObjects.TableSyncer - для таблиц
SyncObjects.InputSyncer - для буфера обмена
Если счетчик организован на файле, в который записывается каждый раз и читается в несколько потоков, то здесь как лочить?
 
Если счетчик организован на файле, в который записывается каждый раз и читается в несколько потоков, то здесь как лочить?
если работа только в одном шаблоне, но у него несколько потоков, то в общем коде создаешь общий объект и лочишь через него.
если нужна блокировка в нескольких проектах, то надо локер создавать в глобальных переменных и лочить его.
 
Подскажите, как сделать lock запроса с паузой?

Т. е. например шаблон работает в 100 потоков. Но в одном месте он дергает GET запрос одного сервиса. И нужно чтобы не раздражать сервис массированными запросами, дергать его не одновременно (по очереди) и с паузой.
Как это можно реализовать?
 
Подскажите, как сделать lock запроса с паузой?

Т. е. например шаблон работает в 100 потоков. Но в одном месте он дергает GET запрос одного сервиса. И нужно чтобы не раздражать сервис массированными запросами, дергать его не одновременно (по очереди) и с паузой.
Как это можно реализовать?
делаешь глобалку, заводишь туда дату. в c# в локе опрашиваешь глобалку на предмет выхода текущего времени за пределы таймаута. если не вышел, гуляешь дальше, если вышел за пределы, то ставишь в глобалку текущее время и уходишь по другой линии на запрос.
 
  • Спасибо
Реакции: Astraport
делаешь глобалку, заводишь туда дату. в c# в локе опрашиваешь глобалку на предмет выхода текущего времени за пределы таймаута. если не вышел, гуляешь дальше, если вышел за пределы, то ставишь в глобалку текущее время и уходишь по другой линии на запрос.
Спасибо, я хотел попроще.
Так не будет работать?
C#:
Развернуть Свернуть Копировать
public static object SyncObject = new object();//в общем коде

//в проекте
lock (CommonCode.SyncObject){
    //собственно запрос
  var result = ZennoPoster.HttpGet(url, proxy, "UTF-8", ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.HeaderAndBody, timeout, cookies, userAgent, true, 5, AdditionalHeaders: new [] {"Referer: "+referer});
// Случайная пауза
Random rnd = new Random();
System.Threading.Thread.Sleep(rnd.Next(3, 18) * 1000);
}
 
Спасибо, я хотел попроще.
Так не будет работать?
C#:
Развернуть Свернуть Копировать
public static object SyncObject = new object();//в общем коде

//в проекте
lock (CommonCode.SyncObject){
    //собственно запрос
  var result = ZennoPoster.HttpGet(url, proxy, "UTF-8", ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.HeaderAndBody, timeout, cookies, userAgent, true, 5, AdditionalHeaders: new [] {"Referer: "+referer});
// Случайная пауза
Random rnd = new Random();
System.Threading.Thread.Sleep(rnd.Next(3, 18) * 1000);
}
очень, очень плохая идея делать паузу в локе.... все шаблоны в этом месте замрут. 100 потоков будут ждать 100*(3,18 ) секунд = в максимуме последний в очереди шаблон исполнит запрос через 30 минут после в тыкания в лок. Тут многопоток превращается в однопоток по сути. 1 поток сделает столько же работы сколько 100 потоков с таким подходом.
 
  • Спасибо
Реакции: Astraport
Может попробовать дату класть в глобальную переменную?
 
  • Спасибо
Реакции: bigloafer
Подскажите пожалуйста, как правильно залочить таблицу Exel, для добавления определённых строк

Через документацию составил:

IZennoTable table = project.Tables["test"];
//Лочим код изменения списка для многопотока
lock (SyncObjects.TableSyncer){
//Добавляем в список "Список 1" элемент со значением "строка"
table.AddRow("строка");
}

Но теперь вопрос, как прописать правильно разделители?
 
Подскажите пожалуйста, как правильно залочить таблицу Exel, для добавления определённых строк

Через документацию составил:

IZennoTable table = project.Tables["test"];
//Лочим код изменения списка для многопотока
lock (SyncObjects.TableSyncer){
//Добавляем в список "Список 1" элемент со значением "строка"
table.AddRow("строка");
}

Но теперь вопрос, как прописать правильно разделители?
C#:
Развернуть Свернуть Копировать
table.AddRow(new[]{"строка1","строка2","строка3" });
 
  • Спасибо
Реакции: MaxLucky
Но это ещё не всё. Объекты SyncObjects.ListSyncer, SyncObjects.TableSyncer, SyncObjects.InputSyncer берутся из библиотечки Global.dll, что в нашем случае значит, что одни и те же объекты синхронизации применяются не только к разным потокам одного шаблона, но и вообще ко всем запущенным шаблонам.
и решается добавлением своих локеров в коммон коде.
Вопрос такой, если проект пишется в одном кубике с привязкой к .dll, которая собирается в визуал студии
такой локер
C#:
Развернуть Свернуть Копировать
public static object loker = new object();
будет работать в многопотоке?, ведь зенка может запустить несколько процессов в рамках одного шаблона, и этот локер будет у каждого процесса свой?, следовательно локер не сработает.
 
будет работать в многопотоке?, ведь зенка может запустить несколько процессов в рамках одного шаблона, и этот локер будет у каждого процесса свой?, следовательно локер не сработает.
Да, будет работать, в том числе со всеми шаблонами, которые подключены к данной библиотеке (из которой используется локер), независимо от того, как и сколько процессов использует сама ZP для нужд исполнения потоков.
Важная ремарка: так работает только в том случае, если библиотека лежит в ExternalAssemblies в директории с зеннкой, и просто подключена к этим шаблонам через "Ссылки из GAC".
Если использовать функцию "Публикация" ("Опубликовать проект" при вызове контекстного меню по названию шаблона в ProjectMaker), чтобы запаковать шаблон и библиотеку в единый файл с расширением ".zp" - то у каждого такого шаблона будет свой вариант библиотеки, т.е. локер будет работать только для потоков конкретного запакованного шаблона.
 
потоками последовательно, в этих участках многопотока как такового нет
То есть каждый поток работает как шаблон в один поток, в одну задачу или весь шаблон работает только как не многопоточный?
 
То есть каждый поток работает как шаблон в один поток, в одну задачу или весь шаблон работает только как не многопоточный?
Шаблон как правило состоит из большого количества действий. Большая часть этих действий для различных потоков одного шаблона индивидуальна и никак напрямую не связана с такими же действиями с соседнем потоке. Поэтому потоки можно выполнять параллельно, получая многопоточную работу шаблона. Но некоторые из действий может быть нельзя разделить в параллель (например, запись каких-то данных в один-единственный файл каждым из потоков). Поэтому в этих местах (н-р записи в файл) потоки могут встать в очередь, т.к. одновременно только один из них может иметь доступ на запись в этот файл.
Шаблон не перстаёт от этого быть многопоточным, просто в конкретных местах его потоки могут ждать друг друга за доступ к единому ресурсу.
 
  • Спасибо
Реакции: lx2003

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