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

  • Спасибо
Реакции: shtift
они не могут быть потокобезопасными, потому что их логика такого не позволяет. Например, чтобы взять строку с удалением, нужно отдельно взять, отдельно удалить. 2 действия. Если бы был отдельный метод, включающий в себя эти 2 действия, тогда он мог бы быть потокобезопасным
Тут ты прав по той причине, что потокобезопасными коллекциями не могут быть листы, так как структура таких коллекций должна поддерживать добавление/извлечение элемента только с начала или с конца (ConcurrenQueue<T>, ConcurrenStack<T>, BlockingCollection<T>), поэтому коллекции в зеннопостере по дефолту не потокобезопасные, если говорить о коде
 
  • Спасибо
Реакции: LaGir
если добавлять несколько проектов в ЗП из одного шаблона - статик переменные общего кода для них будут общие
Интересный момент, не знал - не приходилось использовать их в таких случаях. Благодарю, поковыряю этот момент подробнее и после конкурса добавлю.

Не пойму откуда вы взяли, что нужно вообще пользоваться этими объектами? Поискал в документации и не встретил упоминания, что в шаблонах нужно синхронизировать через них.
Сдается мне, что они созданы исключительно для внутренней логики ZP. Т.е. пока вся статья выглядит так, что вы изначально пользуетесь тем, чем не стоит, а затем поясняете какие из этого проблемы вытекают.
В том и дело, что почти в каждом сниппете на форуме с локами - используются именно эти объекты. Представители ZennoLab в ответах на форуме так же замечены в неоднократном их использовании в примерах кода. Пруф - поиск по форуму. Соответственно, большая часть пользователей Zenno, кто использует локи (найдя нужный для себя сниппет на форуме) - используют именно эти стандартные объекты.
Плюс, не помню, чтобы кто-то на форуме публиковал сниппеты с другими объектами. Вроде только @amyboose где-то писал, что использует сам ресурс в качестве объекта для лока, если память не изменяет.
Про сам ресурс в качестве объекта для лока - согласен, точно стоило написать, тупо забыл. :-)
 
  • Спасибо
Реакции: Dimionix и shtift
Именно таких бы статей по больше в конкурсе... Спасибо!
 
  • Спасибо
Реакции: LaGir
Для популярных типов внешних ресурсов в ZennoPoster предусмотрено три объекта синхронизации, которые в C#-коде указываются в круглых скобках после lock:
SyncObjects.ListSyncer - для списков
SyncObjects.TableSyncer - для таблиц
SyncObjects.InputSyncer - для буфера обмена
Скажите, а есть способ лочить когда используешь БД MySQL?
 
  • Спасибо
Реакции: Protey
Попробовал работать таким методом.

В общем коде добавил строчку:
C#:
Развернуть Свернуть Копировать
public static object SyncObject_accounts = new object();

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

C#:
Развернуть Свернуть Копировать
// Имя файлов
string[] files = { @"keywords_3.txt", @"keywords_2.txt", @"keywords_1.txt"};
// Формирую путь к файлам
string path = string.Format(@"{0}\{1}", project.Directory, @"data");

// Проверяю есть ли папка - если нет - создаю
if (!Directory.Exists(path)) Directory.CreateDirectory(path);

// Беру имя каждого файла по очереди
foreach (string file in files) {
    lock (CommonCode.SyncObject_accounts){
        // Проверяю существование файла
        if(!File.Exists(string.Format(@"{0}\{1}", path, file))) {
            // Если файл не найден - создаю
            File.Create(string.Format(@"{0}\{1}", path, file));
        }
        // Если файл найден или создан - добавляю в файл текст
        File.WriteAllText(string.Format(@"{0}\{1}", path, file), "текст", Encoding.UTF8);
    }
}

В результате, ошибка в логе.
Код:
Развернуть Свернуть Копировать
06:12:02    Выполнение действия CSharp OwnCode Процесс не может получить доступ к файлу "D:\data\keywords_3.txt", так как этот файл используется другим процессом.

Вопрос, что я делаю не так?
Или, данный способ не распространяется на работу с файлами?
 
Или, данный способ не распространяется на работу с файлами?
Распространяется, но скорее всего лучше использовать какой-нибудь StreamWriter, где явно будет закрытие файла. Я точно не берусь утверждать, но ощущение, что где-то остается работа с файлом. Далее он как список не используется ведь?
 
  • Спасибо
Реакции: BAZAg
Распространяется, но скорее всего лучше использовать какой-нибудь StreamWriter, где явно будет закрытие файла. Я точно не берусь утверждать, но ощущение, что где-то остается работа с файлом. Далее он как список не используется ведь?
Нет, именно в этом виде который я привел в своем сообщении работает без каких либо дополнительных списков.
Имен файлов может быть например 1000.
И постоянно привязывать/отвязывать списки - не удобно.
Подумал, что раз тема есть о работе локов, то должно все работать корректно.
Но, в результате вижу, что не работает - иначе бы данная ошибка не появлялась (и это в одном потоке - а в многопотоке вообще будет ошибка на ошибке).
Получается, что создание этого объекта который должен был бы лочить файл не решает проблему...

Как тогда работать таким образом с файлами (используя File.Create и File.WriteAllText).
Видел, что можно использовать StreamWriter, но думал, что и File.Create и File.WriteAllText должны как-то освобождать ресурсы.
Может нужно что-то типа Dispose () использовать для освобождения файла?
 
А это убийственный глюк у зенки при работе с файлами. Я пытался найти решение под один шаблон но так и не нашел и уже не помню как вышел из ситуации. Попробуй после получения ошибки, через 2-3 сек. запустить по новой операцию обращения к файлу. Думаю удевишся. )
 
  • Спасибо
Реакции: orka13 и BAZAg
А это убийственный глюк у зенки при работе с файлами. Я пытался найти решение под один шаблон но так и не нашел и уже не помню как вышел из ситуации. Попробуй после получения ошибки, через 2-3 сек. запустить по новой операцию обращения к файлу. Думаю удевишся. )
Через 2-3 секунды выполняется успешно.
Потом последующий запуск - обратно ошибка.
Это для меня не жизненно важно, просто хотелось бы разобраться один раз как правильно работать с файлами в многопотоке.
Ведь с картинками/каптчей возможно такие же велосипеды...
 
Через 2-3 секунды выполняется успешно.
Потом последующий запуск - обратно ошибка.
Мистика, не правда ли? :)
Да, разобраться не мешало бы и решить проблему. Не знаешь когда столкнешься с ней повторно и в каком месте.
 
Мистика, не правда ли? :-)
Да, разобраться не мешало бы и решить проблему. Не знаешь когда столкнешься с ней повторно и в каком месте.

Одел File.Create в using и заработало :)
Рабочий пример выглядит так.
Осталось еще в многопотоке проверить и определиться нужен ли этот объект синхронизации или не нужен.

C#:
Развернуть Свернуть Копировать
// Имя файлов
string[] files = { @"keywords_3.txt", @"keywords_2.txt", @"keywords_1.txt"};
// Формирую путь к файлам
string path = string.Format(@"{0}\{1}", project.Directory, @"data");

// Проверяю есть ли папка - если нет - создаю
if (!Directory.Exists(path)) Directory.CreateDirectory(path);

// Беру имя каждого файла по очереди
foreach (string file in files) {   
        // Проверяю существование файла
        if(!File.Exists(string.Format(@"{0}\{1}", path, file)) {
            // Если файл не найден - создаю
          //File.Create(string.Format(@"{0}\{1}", path, file));
            using ( File.Create(string.Format(@"{0}\{1}", path, file))) {};
        }
        // Если файл найден или создан - добавляю в файл текст
    File.WriteAllText(string.Format(@"{0}\{1}", path, file), "текст", Encoding.UTF8);
}
 
  • Спасибо
Реакции: Nike59 и one
Одел File.Create в using и заработало :-)
Интересно) Что-то я даже не задумывался о таком "финте ушами". Расскажи потом как в многопотоке будет, если 1 и тот же файл кучей потоков обрабатывать таким способом (особенно интересует File.WriteAllText)
 
Одел File.Create в using и заработало :-)
Рабочий пример выглядит так.
Осталось еще в многопотоке проверить и определиться нужен ли этот объект синхронизации или не нужен.

C#:
Развернуть Свернуть Копировать
// Имя файлов
string[] files = { @"keywords_3.txt", @"keywords_2.txt", @"keywords_1.txt"};
// Формирую путь к файлам
string path = string.Format(@"{0}\{1}", project.Directory, @"data");

// Проверяю есть ли папка - если нет - создаю
if (!Directory.Exists(path)) Directory.CreateDirectory(path);

// Беру имя каждого файла по очереди
foreach (string file in files) {  
        // Проверяю существование файла
        if(!File.Exists(string.Format(@"{0}\{1}", path, file)) {
            // Если файл не найден - создаю
          //File.Create(string.Format(@"{0}\{1}", path, file));
            using ( File.Create(string.Format(@"{0}\{1}", path, file))) {};
        }
        // Если файл найден или создан - добавляю в файл текст
    File.WriteAllText(string.Format(@"{0}\{1}", path, file), "текст", Encoding.UTF8);
}
зачем вообще проверять существование и создавать файл? убери это
 
  • Спасибо
Реакции: LaGir
зачем вообще проверять существование и создавать файл? убери это
Потому что не всегда может быть операция записать в файл, а может быть например сразу по пути перевести в base64 - и тогда гарантировано будет ошибка что мол нет файла.
Хотя, я могу ошибаться, просто проще перестраховаться наперёд, да и логически вродебы правильно - если файла нет то что с ним собственно можно тогда делать?

Интересно) Что-то я даже не задумывался о таком "финте ушами". Расскажи потом как в многопотоке будет, если 1 и тот же файл кучей потоков обрабатывать таким способом (особенно интересует File.WriteAllText)
Наверно в многопотоке придется все-таки этот объект синхронизации использовать.
Но, пока этот момент не проверял.
Я чисто поверил на слово автору статьи, и просто сразу по-умолчанию использовал данную фишку.
А потом оказалось что выдает ошибку и решил разобраться почему этот lock не спасает.
Вот только впринципе логично - если должен спасать от многопотока, то явно не должен от ошибок в логике кода и не понимания, как вообще правильно работать с файлами в C#.
 
Вопрос, что я делаю не так?
Добавлю, что мистики никакой нет, просто метод Create возвращает объект FileStream, для возможности дальнейшей работы с файлом.
FileStream1.png

Поэтому можно просто сразу закрыть его методом Close. Оборачивание в юзинг, впрочем, делает практически то же самое.
C#:
Развернуть Свернуть Копировать
File.Create(path).Close();


Соответственно, лок тут вообще не при чём:
А потом оказалось что выдает ошибку и решил разобраться почему этот lock не спасает.
Вот только впринципе логично - если должен спасать от многопотока, то явно не должен от ошибок в логике кода и не понимания, как вообще правильно работать с файлами в C#.
 
  • Спасибо
Реакции: Metrix и BAZAg
Необходимо создать свои собственные объекты синхронизации в Общем коде. По умолчанию там даже один уже есть:

04-png.25706

Пожалуйста, объясните кто-нибудь на пальцах, как сделать это в Code Creator?
 
Пожалуйста, объясните кто-нибудь на пальцах, как сделать это в Code Creator?
Вставить такие строчки объвления в любой подходящий класс, точно так же, как в Общем коде ProjectMaker.

Например, создаём файл для класса с объектами синхронизации:

2018-05-16_12-53-53.png


Даём подходящее название классу, заполняем его:

2018-05-16_12-59-48.png


После этого можно использовать локи с этими объектами в любых методах проекта:
C#:
Развернуть Свернуть Копировать
lock (Lock.ProxyList)
{
    //... Тут действия со списком прокси, которые необходимо заблокировать
}
 
  • Спасибо
Реакции: uf0log
Спасибо!
 
для лока файлов которые используют разные шаблоны - это годится или это не тот велосипед?
Можно использовать стандартные локи, или вынести свои в dll, подключив её к этим шаблонам (т.е. чтобы локи были как внешний общий ресурс).
 
  • Спасибо
Реакции: arhip1985
Можно использовать стандартные локи, или вынести свои в dll, подключив её к этим шаблонам (т.е. чтобы локи были как внешний общий ресурс).
Если вас не затруднит, то есть пример либы?
и еще момент, а если в общий код разных шахов добавить один и тот же код Лока?
 
Если вас не затруднит, то есть пример либы?
На форуме по-моему несколько тем было по созданию либ в Visual Studio (вот например +- статья по теме). В данном случае нужно просто перенести локи из общего кода в либу, либу собрать и подключить к шаблонам - и можно пользоваться локами из либы.
и еще момент, а если в общий код разных шахов добавить один и тот же код Лока?
Насколько помню, для разных шаблонов это будут разные локи (так как и блок общего кода у каждого будет свой). В копиях одного и того же шаблона локи, соответственно, будут так работать (блок общего кода будет один на все копии шаба).
 
Понадобилось мне сделать, чтобы когда какой-то шаблон работает с файлом, чтобы все остальные не трогали.

Начал делать лок
lock (SyncObjects.ListSyncer)

а там пишут, что он устарел и нужно использовать новый лок
lock (FileSyncObjects.ListSyncer)

Вопрос.
Новый FileSyncObjects.ListSyncer тоже блокирует все шаблоны?
Если один использует турникет, все остальные заблокированы, даже на соседних станциях метро? )))

p.s. Про метро, отличнейший пример. :ay:
 
Начал делать лок
lock (SyncObjects.ListSyncer)

а там пишут, что он устарел и нужно использовать новый лок
lock (FileSyncObjects.ListSyncer)
Не знаю, кто такое пишет. Но вот этот лок, отлично работает со списками.
C#:
Развернуть Свернуть Копировать
lock(SyncObjects.ListSyncer)
 
Не знаю, кто такое пишет.
Команда зеннолаба.
Так и пишут в библиотеке, что SyncObjects.ListSyncer является устаревшим, используйте FileSyncObjects.ListSyncer.


Код:
Развернуть Свернуть Копировать
public class SyncObjects
{
    [Obsolete("Use FileSyncObjects.ListSyncer instead.")]
    public static readonly object ListSyncer;
    
    [Obsolete("Use FileSyncObjects.TableSyncer instead.")]
    public static readonly object TableSyncer;
    
    public static readonly object InputSyncer;

    public SyncObjects();
}

Может админы или модераторы прокомментируют?
 
  • Спасибо
Реакции: Mikhail B.

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