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

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
если не важно изменение, то не надо.
Лочить, только если важно изменение данных.
Допустим вы регистрируете аккаунты, и у вас в файле лежат доступы к почтам.
Список
email1:pass1
email2:pass2
email3:pass3
email4:pass4
email5:pass5

Вам нельзя чтобы несколько потоков начали регистрировать аккаунты с одним и тем же email-ом, вот тогда нужно блокировать,
чтобы каждый поток отработал полный цикл
Цикл у нас, берём первую строку, и удаляем её после взятия.

1-й поток
1) заблокировал файл,
2) взял email, email1:pass1
3) удалил его из списка, email1:pass1
4) и снял блокировку чтобы другой поток мог сделать тоже самое.

2-й поток
1) заблокировал файл,
2) взял email, email2:pass2
3) удалил его из списка, email2:pass2
4) и снял блокировку чтобы другой поток мог сделать тоже самое.

3-й поток
1) заблокировал файл,
2) взял email, email3:pass3
3) удалил его из списка, email3:pass3
4) и снял блокировку чтобы другой поток мог сделать тоже самое.


А если не ставить блокировку, то будет вот так приблизительно:
1-й поток
взял email, email1:pass1

в этот момент
2-й поток
взял email, email1:pass1

в этот момент
3-й поток
взял email, email1:pass1

Затем в коде идёт удаление email-a (певой строки)
1-й поток
удалил его из списка, email1:pass1

в этот момент
2-й поток
удалил его из списка, email2:pass2

в этот момент
3-й поток
удалил его из списка, email3:pass3



И в итоге у вас 3 потока с одним и тем же ящиком: email1:pass1
А ящики
email2:pass2
email3:pass3

совсем не использовались, но были удалены из списка

И из этих 3-х потоков зарегистрирует аккаунт только какой-то один, кто первый успеет.
Да теперь стал больше понимать, а то лок, лок, для много потока, а конкретно, для чего и в каких целях применять хз.
 
  • Спасибо
Реакции: mr.green

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 689
Баллы
113
Т.е. ты не разбираешься, но решил выразить своё авторитетное мнение? Молодец, что тут скажешь :-) :ay:
Чем тебе не нравится лок локальной переменной? Если посмотреть внимательно для чего она, то всё становится понятно. Если мы будем определять индекс строки, с которой будем работать вне лока, то однажды получим исключение "Индекс находился за пределами диапазона", потому что другой поток уже может удалить строку с этим индексом (например, она была последней). А то, что объявление переменной внутри лока, это ничего не меняет существенно.
Ты понимаешь смысл блокировки общими объектами? Если ты про SyncObjects.ListSyncer, то это общий объект для всех списков всех шаблонов, соответственно, общая очередь. Если ты про специально созданные статические объекты для блокировки public static object startListLocker = new object(); так в проекте есть кубик ниже того, что со стрелкой. Минусы подхода с блокировкой специально созданными локерами тоже есть: можно запутаться при наличии большого количества списков в шаблоне, если методы работы со списками вынесены в общий код, то дополнительно придётся прокидывать для работы с каждым списком свой локер, что также может вызвать путаницу.
По поводу бантика, посмотри внимательно пост, который процитирован и подумай ещё раз.
Доступ к объекту можно блокировать этим же самым объектом, в случае со списками/таблицами Зеннопостера это не так.

Лок нужно стремиться делать максимально коротким по времени, для совершения манипуляций со списком, поэтому, например, если нам надо взять строку с удалением из списка и потом распарсить её, то лочим мы только взятие и удаление, а парсим за пределами лока. Если же нам надо сделать изменения в части строки, то нам нужно взять строку, определить её индекс, удалить строку, сделать изменения в строке и вставить уже эту обновлённую строку в список по этому же индексу, всё это нужно будет проделать в пределах одного лока
Ты решил потролить троля с форума ? Оригинально ;-)
Да мне пофиг как вы там оба лочить будете, разве не ясно из тона моего поста ? Странно, наверно язвительную хватку теряю ;-)
Вместо многа букавок в мою сторону, лучше бы написал человеку пример кода с работающей блокировкой через локальную переменную, а то у него не работает что то.
А то болтовней тут все горазды заниматься, прям как я *HAHA*
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
Да теперь стал больше понимать, а то лок, лок, для много потока, а конкретно, для чего и в каких целях применять хз.
Чтобы гарантировать одним потоком получение первой строки и удаление её же, нужно всё располагать в коде между {}.
lock:
lock(Locker.startList)
{
    // Получаем первую строку
    var email = startList[0];
    
    // Удаляем первую строку
    startList.RemoveAt(0);
}

// Остальная логика которая не относится к работе со списком.
Два действия, которые будут выполнены без вмешательства других потоков.
Все остальные потоки, которые работают с этим списком (а вернее с этим локом), не будут входить в эту конструкцию lock(Locker.startList) {//} пока не выполнится код того потока, который зашёл туда первым.​
 
  • Спасибо
Реакции: Roman48

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
Чтобы гарантировать одним потоком получение первой строки и удаление её же, нужно всё располагать в коде между {}.
lock:
lock(Locker.startList)
{
    // Получаем первую строку
    var email = startList[0];
   
    // Удаляем первую строку
    startList.RemoveAt(0);
}

// Остальная логика которая не относится к работе со списком.
Два действия, которые будут выполнены без вмешательства других потоков.
Все остальные потоки, которые работают с этим списком (а вернее с этим локом), не будут входить в эту конструкцию lock(Locker.startList) {//} пока не выполнится код того потока, который зашёл туда первым.​
У меня так, заменю сейчас на ваш код
C#:
lock(SyncObjects.ListSyncer){
   project.Variables["region"].Value = project.Lists["Регион"][0].Trim();
   project.Lists["Регион"].RemoveAt(0);
}
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
У меня так, заменю сейчас на ваш код
У вас внутренность лока такая же.
Вам просто нужно создать отдельный объект для локинга этого списка в общем коде.
C#:
public class Locker
{
    public static object Регион = new object();
}
C#:
lock(Locker.Регион)
{
     //
}
На русском тоже будет работать, но лучше делать на английском ;-)
 
  • Спасибо
Реакции: Roman48

Metrix

Client
Регистрация
03.01.2014
Сообщения
343
Благодарностей
271
Баллы
63
Всё правильно.
Нужно использовать статический неизменяемый локер для каждого отдельного объекта (если он нужен).
Если 10 списков, то нужно заводить 10 статических локеров, и никак не использовать сам список в качестве локера.

Статью, конечно же читал, в ней нет информации про блокировку доступа к объекту самим же объектом, но на практике это часто встречается.
Получается, что автор статьи был прав, а его статью поставили под сомнение и никто в пылу споров не обратил внимание на то, что блокировка доступа к Зенносписку самим зенносписком таит в себе сюрпризы дублей и пересечений между потоками.
Или вообще можно сделать отдельный класс локеров, а локеры называть именами объектов
C#:
public class Locker
{
public static object startList = new object();
public static object endList = new object();
public static object secondList = new object();
public static object secondTable = new object();
}
А вызывать вот так
C#:
lock(Locker.startList)
{
startList.Add("");
}
Да, это хороший вариант, спасибо!
 

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
У вас внутренность лока такая же.
Вам просто нужно создать отдельный объект для локинга этого списка в общем коде.
C#:
public class Locker
{
    public static object Регион = new object();
}
C#:
lock(Locker.Регион)
{
     //
}
На русском тоже будет работать, но лучше делать на английском
У меня такой общий код, на примере можете пожалуйста показать, как вставить в общий код, два или три списка? ;-)
C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;
using ZennoLab.CommandCenter;
using ZennoLab.InterfacesLibrary;
using ZennoLab.InterfacesLibrary.ProjectModel;
using ZennoLab.InterfacesLibrary.ProjectModel.Collections;
using ZennoLab.InterfacesLibrary.ProjectModel.Enums;
using ZennoLab.Macros;
using Global.ZennoExtensions;
using ZennoLab.Emulation;
using System.Xml;
using System.Runtime.Serialization;
namespace ZennoLab.OwnCode
{
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class CommonCode
    {
        /// <summary>
        /// Lock this object to mark part of code for single thread execution
        /// </summary>
        public static object SyncObject = new object();

        // Insert your code here
    }
}
public static class ZHelpers
    {
        private static string[] LoadStates = {"complete", "uninitialized", }; //Статусы которые считаем что документ загрузился
        
        /// <summary>
        /// Ожидание загрузки таба
        /// </summary>
        /// <param name="tab">Таб загрузки которого ждем</param>
        /// <param name="maxWaitMs">Максимальное ожидание в мс, по умолчанию 60 сек</param>
        public static void TabLoadWait(this Tab tab, int maxWaitMs = 60 * 1000)
        {
            maxWaitMs = maxWaitMs/2;
            //Делаем 2 захода, для точной уверенности
            for (var i = 0; i < 2; i++)
            {
                //TODO заменить на токен
                //Когда выходим
                long maxTime = DateTime.Now.Ticks + maxWaitMs * 10000;
                //Проверям на загрузку странцы пока не кончится время или мы не получим все интересующие нас данные
                do
                {
                
                // TODO: проверка прерывания
                
                    new System.Threading.ManualResetEvent(false).WaitOne(2000);
                    if (tab.IsBusy) tab.WaitDownloading();

                    //Проверяем через js document.readyState, статус всех документов на страницы
                    bool isNotComplete = false;
                    foreach (var document in tab.AllDocuments.Documents)
                    {
                        string readyState = document.EvaluateScript("return document.readyState;");
                        if (!String.IsNullOrEmpty(readyState) && !LoadStates.Contains(readyState))
                        {
                            if (readyState != "interactive" || !document.URL.StartsWith("about:",StringComparison.Ordinal))
                                isNotComplete = true;
                        }
                    }

                    // Если у всех статус complete считаем что прошли проверку
                    if (!isNotComplete)
                        break;
                }
                while (DateTime.Now.Ticks < maxTime);
            }
        }
    }
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
Статью, конечно же читал, в ней нет информации про блокировку доступа к объекту самим же объектом, но на практике это часто встречается.
В вашем коде (с блокировками доступа "на себя") в такой блокировке идут повторы, как вы писали вот здесь.
Погуглил, и вроде бы при локе "на себя" и изменении объекта "себя" в этом локе (допустим удаление строки) другой поток может получить значение из кеша, и получить удалённую строку, из-за этого и получаются дубли.


C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;
using ZennoLab.CommandCenter;
using ZennoLab.InterfacesLibrary;
using ZennoLab.InterfacesLibrary.ProjectModel;
using ZennoLab.InterfacesLibrary.ProjectModel.Collections;
using ZennoLab.InterfacesLibrary.ProjectModel.Enums;
using ZennoLab.Macros;
using Global.ZennoExtensions;
using ZennoLab.Emulation;
using System.Xml;
using System.Runtime.Serialization;
namespace ZennoLab.OwnCode
{
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class CommonCode
    {
        /// <summary>
        /// Lock this object to mark part of code for single thread execution
        /// </summary>
        public static object SyncObject = new object();

        // Insert your code here
    }
}
public static class ZHelpers
    {
        private static string[] LoadStates = {"complete", "uninitialized", }; //Статусы которые считаем что документ загрузился
       
        /// <summary>
        /// Ожидание загрузки таба
        /// </summary>
        /// <param name="tab">Таб загрузки которого ждем</param>
        /// <param name="maxWaitMs">Максимальное ожидание в мс, по умолчанию 60 сек</param>
        public static void TabLoadWait(this Tab tab, int maxWaitMs = 60 * 1000)
        {
            maxWaitMs = maxWaitMs/2;
            //Делаем 2 захода, для точной уверенности
            for (var i = 0; i < 2; i++)
            {
                //TODO заменить на токен
                //Когда выходим
                long maxTime = DateTime.Now.Ticks + maxWaitMs * 10000;
                //Проверям на загрузку странцы пока не кончится время или мы не получим все интересующие нас данные
                do
                {
               
                // TODO: проверка прерывания
               
                    new System.Threading.ManualResetEvent(false).WaitOne(2000);
                    if (tab.IsBusy) tab.WaitDownloading();

                    //Проверяем через js document.readyState, статус всех документов на страницы
                    bool isNotComplete = false;
                    foreach (var document in tab.AllDocuments.Documents)
                    {
                        string readyState = document.EvaluateScript("return document.readyState;");
                        if (!String.IsNullOrEmpty(readyState) && !LoadStates.Contains(readyState))
                        {
                            if (readyState != "interactive" || !document.URL.StartsWith("about:",StringComparison.Ordinal))
                                isNotComplete = true;
                        }
                    }

                    // Если у всех статус complete считаем что прошли проверку
                    if (!isNotComplete)
                        break;
                }
                while (DateTime.Now.Ticks < maxTime);
            }
        }
    }
Я так понимаю это вопрос куда добавить Locker?
C#:
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class CommonCode
    {
        /// <summary>
        /// Lock this object to mark part of code for single thread execution
        /// </summary>
        public static object SyncObject = new object();

        // Insert your code here
    }

    public class Locker
    {
        public static object Регион = new object();
    }
 
  • Спасибо
Реакции: Rain и Roman48

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
В вашем коде (с блокировками доступа "на себя") в такой блокировке идут повторы, как вы писали вот здесь.
Погуглил, и вроде бы при локе "на себя" и изменении объекта "себя" в этом локе (допустим удаление строки) другой поток может получить значение из кеша, и получить удалённую строку, из-за этого и получаются дубли.



Я так понимаю это вопрос куда добавить Locker?
C#:
    /// <summary>
    /// A simple class of the common code
    /// </summary>
    public class CommonCode
    {
        /// <summary>
        /// Lock this object to mark part of code for single thread execution
        /// </summary>
        public static object SyncObject = new object();

        // Insert your code here
    }

    public class Locker
    {
        public static object Регион = new object();
    }
Да локер, а если три файла, Как их вставить?

public class Locker
{
public static object Регион, Прокси, Темп, Карта, Парсинг = new object();
}
 

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
Догадался с новой строки)
C#:
public class Locker
    {
        public static object Регион = new object();
    public static object Регион1 = new object();
    public static object Регион2 = new object();
    }
 

volody00

Client
Регистрация
06.09.2016
Сообщения
793
Благодарностей
811
Баллы
93
ZSharp , подскажи, если у меня static список в общем коде (без привязки к файлу), например, public static List<string> spisok = new List<string>(); надо ли лочить при записи в него?

И как по твоему, есть ли вообще смысл их использовать вместо использования IZennoList (только при завершении перекидывая всё в файл на пк) ? Спасибо
 

Metrix

Client
Регистрация
03.01.2014
Сообщения
343
Благодарностей
271
Баллы
63
В вашем коде (с блокировками доступа "на себя") в такой блокировке идут повторы, как вы писали вот здесь.
Погуглил, и вроде бы при локе "на себя" и изменении объекта "себя" в этом локе (допустим удаление строки) другой поток может получить значение из кеша, и получить удалённую строку, из-за этого и получаются дубли.
Да, встречал информацию, наподобие этой. Что доступ к коллекции лочить ею же самой, при вероятности её изменения, не самый хороший вариант. А если не для изменения, то для чего ещё может понадобиться блокировка.
В общем, статические локеры рулят.
 

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
С этим локом, шаблон каждый раз приходиться запускать сначала, вот делаешь шаблон, потом добавил код, хотя бы тот что ниже, нажимаешь на кубик выполнить, он не выполняется, а когда шаблон нажал сначала и кубик потом отрабатывает как надо, правильно, или так не должно быть?
C#:
public class Locker
    {
        public static object Прокси = new object();
        public static object Регион = new object();
        public static object Парсинг = new object();
        public static object Карта = new object();
    }

lock(Locker.Парсинг)
{   
IZennoList list = project.Lists["Парсинг"];
string str = project.Variables["sitemap_1"].Value;
if (list.Any(s => s == str)) { // если хотя бы одна строка списка равна значению переменной
    project.SendInfoToLog("Такая закупка уже есть");
    throw new Exception(); // выход будет по красной стрелке (можно вывести на нейтральный кубик)
}
// если ни одна строка не равна - выход по зелёной
}

lock(Locker.Парсинг)
{   
    project.Lists["Парсинг"].Add(project.Variables["sitemap_1"].Value);
}

И Т.Д
 

volody00

Client
Регистрация
06.09.2016
Сообщения
793
Благодарностей
811
Баллы
93
С этим локом, шаблон каждый раз приходиться запускать сначала, вот делаешь шаблон, потом добавил код, хотя бы тот что ниже, нажимаешь на кубик выполнить, он не выполняется, а когда шаблон нажал сначала и кубик потом отрабатывает как надо, правильно, или так не должно быть?
C#:
public class Locker
    {
        public static object Прокси = new object();
        public static object Регион = new object();
        public static object Парсинг = new object();
        public static object Карта = new object();
    }

lock(Locker.Парсинг)
{  
IZennoList list = project.Lists["Парсинг"];
string str = project.Variables["sitemap_1"].Value;
if (list.Any(s => s == str)) { // если хотя бы одна строка списка равна значению переменной
    project.SendInfoToLog("Такая закупка уже есть");
    throw new Exception(); // выход будет по красной стрелке (можно вывести на нейтральный кубик)
}
// если ни одна строка не равна - выход по зелёной
}

lock(Locker.Парсинг)
{  
    project.Lists["Парсинг"].Add(project.Variables["sitemap_1"].Value);
}

И Т.Д
не норма. скинь шаблон, поправлю
 
  • Спасибо
Реакции: Roman48

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
если у меня static список в общем коде (без привязки к файлу), например, public static List<string> spisok = new List<string>(); надо ли лочить при записи в него?
Тут так же всё зависит от того, что там.
Если это справочная информация, для рандом имён и т.д. то нет, а если так как я указывал выше, то нужно лочить.
То есть если список неизменяемый, то лок в принципе не нужен. А если список изменяется то лучше лочить.
Да и чтобы не было ошибки, когда один поток открыл файл, а у другого нет доступа, то лучше лочить. Как минимум при чтении/сохранении файла желательно лочить.

И как по твоему, есть ли вообще смысл их использовать вместо использования IZennoList (только при завершении перекидывая всё в файл на пк)
Тут всё зависит от самого шаблона, и от знаний кода.
Если шаблон на пару кубиков, то можно конечно оставить и IZennoList, а если большая часть шаблонов пишете на C#, то лучше использовать C# конструкции как new List<string>.

А вот по поводу статического списка, чем раньше откажетесь тем лучше.
Я создавал по статике тему и на форуме, и списывался с разрабами.
Статика в ZennoPoster немного работает не так как в обычном приложении на C#.
Допустим вы создали статический список
C#:
public static List<string> spisok = new List<string>();
Вы писали про сохранение в конце шаблона в файл, то есть давайте представим и в начале вы читаете этот файл в spisok.

При запуске 1-го потока шаблона
1) создаёт новый список spisok.
2) Вы добавляете в него какие-то данные. (чтение файла)
3) Что-то делаете с этим списком.

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

Но в вашем коде 2-й поток
опять
1) создаёт новый список spisok.
2) Вы добавляете в него какие-то данные. (чтение файла)
3) Что-то делаете с этим списком.

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

Но если у вас будет обычный список (без статик)
C#:
public List<string> spisok = new List<string>();
То будет создаваться свой список внутри потока, который не нужно лочить, так как его другие потоки не видят.
Будет в каждом потоке свой уникальный список.

А если static то нужно менять логику шаблона.

Опять же не знаю для чего это список.
Но представим что этот список proxy, и работает так:
1) Создали новый список spisok.
2) Прочитали файл (proxy.txt) в spisok
3) Взяли первую строку из списка
4) Удалили эту первую строку
5) Записали эту строку в конец списка
6) Сохранили изменения в файл.

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

Общий код:
public class YourCode
{
    public static List<string> spisok; // БЕЗ new List<string>
    public static object lockSpisok = new object();
}
кубик:
// Путь к файлу который нужно читать в список
string pathFile = @"C:\papka\proxy.txt";
// Переменная под прокси
string proxy = "";

lock (YourCode.lockSpisok)
{
    // Если список не существует то создадим его.
    if (YourCode.spisok == null)
    {
        // Создадим список
        YourCode.spisok = new List<string>();

        // И добавим в него данные из файла.
        YourCode.spisok = File.ReadAllLines(pathFile).ToList();

        // Удалить дубли
        YourCode.spisok = YourCode.spisok.Distinct().ToList();

        // Удалить пробельные символы
        YourCode.spisok.RemoveAll(x => string.IsNullOrWhiteSpace(x));
    }


    // Взять первую строку
    proxy = YourCode.spisok[0];

    // Удалить первую строку
    YourCode.spisok.RemoveAt(0);

    // Добавить взятую строку в конец файла.
    YourCode.spisok.Add(proxy);
}

// Установить proxy
instance.SetProxy(proxy);
А если это всё связано именно с одиночным получением данных (как на примере с прокси) то этот список вообще не нужен.

Можно создать метод в общем коде для получения строки
Общий код:
public class YourCode
{
    private static object lockFileProxy = new object();
    
    public static string GetProxy(string pathFile)
    {
        string proxy = "";

        lock (lockFileProxy)
        {
            // Читаем файл
            var list = File.ReadAllLines(pathFile).ToList();

            // Удалить дубли
            list = list.Distinct().ToList();

            // Удалить пробельные символы
            list.RemoveAll(x => string.IsNullOrWhiteSpace(x));

            // Взять первую строку
            if (list.Count > 0)
            {
                proxy = list[0];

                // Удалить первую строку
                list.RemoveAt(0);

                // Добавить взятую строку в конец файла.
                list.Add(proxy);
            }

            // Записать изменения в файл
            File.WriteAllLines(pathFile, list);
        }

        return proxy;
    }
}
В кубике:
// Путь к файлу который нужно читать в список
string pathFile = @"C:\papka\proxy.txt";

// Переменная под прокси
string proxy = YourCode.GetProxy(pathFile);
 

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113

Вложения

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
Уже не помню для чего, я копирую детективы и gaс ссылки из других шаблонов, для какого шаблона уже не помню
ну их можно удалить это родные библиотеки ZennoPoster.
 
  • Спасибо
Реакции: Roman48

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
Это я выше часть шаблона скопировал. Нахер, весь день потратил и ни чего не работает, с общим кодом, и с локами, ведь не понимаю, а полез, обойдусь обычным локом.
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
Но зачем то они там добавлены.
Это родные библиотеки ZennoPoster, они и так есть без добавления.
Ну для проверки удалите эти библиотеки из GAC, и попробуйте останется ошибка или нет?
 
  • Спасибо
Реакции: Roman48

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
Это родные библиотеки ZennoPoster, они и так есть без добавления.
Ну для проверки удалите эти библиотеки из GAC, и попробуйте останется ошибка или нет?
4 штуки?
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113
Работает, прокси спарсил, карту с сайта скачал, обработал
 

ZSharp

Client
Регистрация
29.09.2013
Сообщения
387
Благодарностей
121
Баллы
43
  • Спасибо
Реакции: Roman48

Roman48

Client
Регистрация
28.02.2016
Сообщения
2 058
Благодарностей
742
Баллы
113

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 367
Благодарностей
3 292
Баллы
113

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 790
Благодарностей
5 689
Баллы
113
Данная переменная своя для каждого шаблона и не подходит для блокировки.
да он не понимает. я ему написал вон выше что локальные переменные не подходят для лока многопотока, в ответ только тролинг получил.
а с другой стороны, наши ли это проблемы ? думаю что нет, поэтому пусть лочит как хочет :-)
 

Yuriy Zymlex

Moderator
Команда форума
Регистрация
24.10.2016
Сообщения
6 367
Благодарностей
3 292
Баллы
113
да он не понимает. я ему написал вон выше что локальные переменные не подходят для лока многопотока, в ответ только тролинг получил.
Там проблема больше, возвращаемый объект списка разный у шаблонов.
 

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