Обьясните как работает lock(SyncObjects.TableSyncer)

  • Автор темы Автор темы Art4D
  • Дата начала Дата начала

Art4D

Client
Регистрация
22.08.2014
Сообщения
276
Реакции
48
Баллы
28
На сколько я понял эти локи работают по ИМЕНИ ТАБЛИЦЫ?
Не по адресу расположения таблицы, а именно имени в PM, так?
И применять их надо только если нужен многопоток?
 
На сколько я понял эти локи работают по ИМЕНИ ТАБЛИЦЫ?
Нет, они работают по ссылочному элементу, таблица как раз ссылается на элемент в куче (можешь не вникать в это, не обязательно понимать).
Не по адресу расположения таблицы, а именно имени в PM, так?
Можно поставить любой ссылочный элемент и блокировать им. В некоторых случаях (с этим надо быть осторожным) можно блокировать таблицу обычным названием переменной string
И применять их надо только если нужен многопоток?
Да, если нету многопотока, можешь забыть об этой строке и удалить её нахер
 
Нет, они работают по ссылочному элементу, таблица как раз ссылается на элемент в куче (можешь не вникать в это, не обязательно понимать).
А как лок работает?
1. Например есть 2 шаблона, в каждом есть таблица "table", и таблицы заполняются в проекте (без загрузки из файла), при одновременной работе этих шаблонов, один из шаблонов будет лочить другой пока не выполнится сниппет другого шаба?
2. Пример, тоже самое что в 1, только таблицы имеют разные названия, но они загружаются из одного файла. Будут ли один шаб стопить другой из за лока?
 
Вот у меня проблема.
Есть шаб, в котором таблица загружается из файла (не редактируется)
И есть второй шаб, который работает в многопотоке с локом с этой же таблицей и записывает в ней данные.

Первый шаб все время стопится из-за того, что многопоточный шаб локает эту таблицу.
В обоих шаблонах название таблицы одинаковое.
Мне надо сменить название таблицы в первом шабе или это никак не пофиксить?
 
А как лок работает?
1. Например есть 2 шаблона, в каждом есть таблица "table", и таблицы заполняются в проекте (без загрузки из файла), при одновременной работе этих шаблонов, один из шаблонов будет лочить другой пока не выполнится сниппет другого шаба?
2. Пример, тоже самое что в 1, только таблицы имеют разные названия, но они загружаются из одного файла. Будут ли один шаб стопить другой из за лока?
1) Если это разные шаблоны, которые запущены одновременно, то они друг на друга не влияют и ничего блокировать не нужно вне зависимости от названия таблицы. На 100% не уверен в этом, так как внутреннюю реализацию зенки знают только сами разрабы зенки. Я лично предполагаю, что там они идут независимо.
2) Стопить не будут, но при загрузке из файла может вылезти ошибка доступа. Плюс при сохранении изменений они могут конфликтовать
 
Помогите, пожалуйста,
Вот у меня проблема.
Есть шаб, в котором таблица загружается из файла (не редактируется)
И есть второй шаб, который работает в многопотоке с локом с этой же таблицей и записывает в ней данные(таблица из файла, с сохранением)

Первый шаб все время стопится из-за того, что многопоточный шаб локает эту таблицу.
Названия менял таблиц и все равно стопит шаблон.
Как вариант можно конечно таблицу перекопировать в другую и с ней работать, но это так себе вариант.
Может есть более оптимальный вариант?

Самое тупое, это то что шаб стопится, когда эта таблица НЕ ИСПОЛЬЗУЕТСЯ.
Пожалуйста, объясните как нормально эту ситуацию пофиксить?
 
Вероятно, ты обернул в лок не тот участок кода. Лочить надо только непосредственно сами операции над таблицами, которые должны отрабатывать мгновенно.
 
Вероятно, ты обернул в лок не тот участок кода. Лочить надо только непосредственно сами операции над таблицами, которые должны отрабатывать мгновенно.
Я локнул в одном шабе кусок кода, в котором большой цикл, который обрабатывается ~30сек. Как раз на это время лочится другой шаб, в котором есть эта таблица, НО она в нем без сохранения и НЕ используется тогда, когда шаб лочит.
Может я чего-то не знаю или упустил.
 
Я локнул в одном шабе кусок кода, в котором большой цикл, который обрабатывается ~30сек. Как раз на это время лочится другой шаб, в котором есть эта таблица, НО она в нем без сохранения и НЕ используется тогда, когда шаб лочит.
Может я чего-то не знаю или упустил.
Тебе не нужно лочить весь цикл. Локни только ту строку (строки), где ты меняешь данные в таблице. Прямо внутри цикла оберни такие строки в лок.
 
  • Оценить
Реакции: Art4D
Как раз на это время лочится другой шаб, в котором есть эта таблица, НО она в нем без сохранения и НЕ используется тогда, когда шаб лочит
Это очень странно. lock не может залочить что-то на много разных шабов. Лочится кусок кода в пределах одного шаба, тогда много потоков одного шаба обрабатывают локнутый кусок кода по очереди. Я думаю, тут что-то другое. Может быть, другой шаб висит, потому что не может получить доступ к файлу, к которому привязана таблица, потому что ему что-то из этой таблицы надо (а ей надо из файла), а в файл долго идёт запись в этот момент. Так может быть если например очень много строк в файле, тогда следующая может долго добавляться. Ну, что-то такое. Т.е. я не знаю, что, я шабов не видела, но как-то так. Ну не может быть лока на 2 разных шаба.

Если дело в огромном файле, то можно сделать вот как.

1. Создаём папку.
2. шаб1, как я поняла, за время своего выполнения пишет много строк в таблицу? (ты сказал, там большой цикл). Но при этом шаб1 не использует сам эти строки. Так вот, шаб1 вообще отказывается от таблицы, в начале генерирует рандомную последовательность букв и цифр, запоминает (получается что-то типа "fgT7yh9ufg"). шаб1 сохраняет строки в файл с именем "fgT7yh9ufg.txt" в папке, которую мы создали. В итоге получится папка, в которой лежит много таких файлов и в каждом, например 1000 строк (это если в длинном цикле было 1000 итераций).
3. В шабе2 (который только использует строки) есть таблица без привязки к файлу. В начале выполнения шаба2 в C# сниппете выбираем рандомный файл из папки из шага 2, читаем из него строки, записываем в эту таблицу.

Но это вот если у тебя ни один из шабов не удаляет эти строки. Ты ничего не написал про удаление, поэтому предполагаю, что его нет. И ещё, если в большом цикле 10 итераций и поэтому получится много файлов с 10 строками - это тоже плохо (будет очень много мелких файлов в одной папке, тогда доступ к ним тоже очень долгий + фрагментация диска) Про это тоже ничего не сказано, поэтому предполагаю, что в цикле много итераций (не просто же так он длится 30 секунд).
 
Последнее редактирование:
  • Оценить
Реакции: Art4D
Тебе не нужно лочить весь цикл. Локни только ту строку (строки), где ты меняешь данные в таблице. Прямо внутри цикла оберни такие строки в лок.
Тут пример нужен, иначе непонятно
 
~30сек он длится, потому что в зенно таблицы работают медленно очень. Пример:
Сниппет, который длится 30 сек:
PHP:
Развернуть Свернуть Копировать
var sourceTable = project.Tables["tabl1"];
var savetable = project.Tables["W"];
var a = true;
lock(SyncObjects.TableSyncer)
{
    for(int i=0; i < sourceTable.RowCount; i++)
    {
        string name = sourceTable.GetCell("A", i);
        string price1 = sourceTable.GetCell("B", i);
        for(int j=0; j < savetable.RowCount; j++)
    {
        string cname = savetable.GetCell("A", j); //читаем ячейку
        if (name==cname)
        {
            string tprice1 = savetable.GetCell("D", j); //читаем ячейку
            double tprice = Convert.ToDouble(tprice1);
            savetable.SetCell("B", j, price1); //сохраняем данные
            double cprice = Convert.ToDouble(price1);
            double k=Math.Round(0.95*tprice*10/cprice);
            string c = Convert.ToString(k);  
            savetable.SetCell("C", j, c); //сохраняем данные
            a = false;
            break;
        }
        a=true;
    }
    if (a==true)
    savetable.AddRow(new [] { name, price1, "1", "1", "1" }); //сохраняем данные
    }
}

А вот тот же самый сниппет, только реализован через списки, работает 5 сек:
PHP:
Развернуть Свернуть Копировать
for (int i=0; i<project.Tables["tabl1"].RowCount; i++)
{
    project.Lists["name"].Add(project.Tables["tabl1"].GetCell(0,i));
    project.Lists["price"].Add(project.Tables["tabl1"].GetCell(1,i));
}
for (int i=0; i<project.Tables["W"].RowCount; i++)
{
    project.Lists["namec"].Add(project.Tables["W"].GetCell(0,i));
    project.Lists["pricec"].Add(project.Tables["W"].GetCell(1,i));
    project.Lists["koefc"].Add(project.Tables["W"].GetCell(2,i));
    project.Lists["tprice"].Add(project.Tables["W"].GetCell(3,i));
}

var firstList = project.Lists["name"];
var secondList = project.Lists["namec"];
var trList = project.Lists["price"];
var fourList = project.Lists["pricec"];
var fiveList = project.Lists["koefc"];
var sixList = project.Lists["tprice"];
var a = true;

    for(int i=0; i < firstList.Count; i++)
    {
        var str1 = firstList[i];
        for(int j=secondList.Count-1; j >= 0; j--)
        {
            var str2 = secondList[j];
            if (str1==str2)
            {
                fourList.RemoveAt(j);
                fourList.Insert(j, trList[i]);
                a = false;
                break;
            }
            a=true;
    }
    if (a==true)
project.Tables["W"].AddRow(new [] { firstList[i], trList[i], "1", "1", "1" });
    }
  
    for(int i=0; i < sixList.Count; i++)
    {
    fiveList.RemoveAt(i);
        double tprice = double.Parse(sixList[i]);
        double pricec = double.Parse(fourList[i]);
    double k=Math.Round(0.95*tprice*10/pricec);
    string c = Convert.ToString(k);      
    fiveList.Insert(i, c);
    }
И далее три списка кладутся в столбцы таблицы.
 
  • Оценить
Реакции: Valiksim
~30сек он длится, потому что в зенно таблицы работают медленно очень. Пример:
Сниппет, который длится 30 сек:
PHP:
Развернуть Свернуть Копировать
var sourceTable = project.Tables["tabl1"];
var savetable = project.Tables["W"];
var a = true;
lock(SyncObjects.TableSyncer)
{
    for(int i=0; i < sourceTable.RowCount; i++)
    {
        string name = sourceTable.GetCell("A", i);
        string price1 = sourceTable.GetCell("B", i);
        for(int j=0; j < savetable.RowCount; j++)
    {
        string cname = savetable.GetCell("A", j); //читаем ячейку
        if (name==cname)
        {
            string tprice1 = savetable.GetCell("D", j); //читаем ячейку
            double tprice = Convert.ToDouble(tprice1);
            savetable.SetCell("B", j, price1); //сохраняем данные
            double cprice = Convert.ToDouble(price1);
            double k=Math.Round(0.95*tprice*10/cprice);
            string c = Convert.ToString(k); 
            savetable.SetCell("C", j, c); //сохраняем данные
            a = false;
            break;
        }
        a=true;
    }
    if (a==true)
    savetable.AddRow(new [] { name, price1, "1", "1", "1" }); //сохраняем данные
    }
}

А вот тот же самый сниппет, только реализован через списки, работает 5 сек:
PHP:
Развернуть Свернуть Копировать
for (int i=0; i<project.Tables["tabl1"].RowCount; i++)
{
    project.Lists["name"].Add(project.Tables["tabl1"].GetCell(0,i));
    project.Lists["price"].Add(project.Tables["tabl1"].GetCell(1,i));
}
for (int i=0; i<project.Tables["W"].RowCount; i++)
{
    project.Lists["namec"].Add(project.Tables["W"].GetCell(0,i));
    project.Lists["pricec"].Add(project.Tables["W"].GetCell(1,i));
    project.Lists["koefc"].Add(project.Tables["W"].GetCell(2,i));
    project.Lists["tprice"].Add(project.Tables["W"].GetCell(3,i));
}

var firstList = project.Lists["name"];
var secondList = project.Lists["namec"];
var trList = project.Lists["price"];
var fourList = project.Lists["pricec"];
var fiveList = project.Lists["koefc"];
var sixList = project.Lists["tprice"];
var a = true;

    for(int i=0; i < firstList.Count; i++)
    {
        var str1 = firstList[i];
        for(int j=secondList.Count-1; j >= 0; j--)
        {
            var str2 = secondList[j];
            if (str1==str2)
            {
                fourList.RemoveAt(j);
                fourList.Insert(j, trList[i]);
                a = false;
                break;
            }
            a=true;
    }
    if (a==true)
project.Tables["W"].AddRow(new [] { firstList[i], trList[i], "1", "1", "1" });
    }
 
    for(int i=0; i < sixList.Count; i++)
    {
    fiveList.RemoveAt(i);
        double tprice = double.Parse(sixList[i]);
        double pricec = double.Parse(fourList[i]);
    double k=Math.Round(0.95*tprice*10/pricec);
    string c = Convert.ToString(k);     
    fiveList.Insert(i, c);
    }
И далее три списка кладутся в столбцы таблицы.
У вас сниппет для таблиц использует лок, а сниппет для списков нет.
Попробуйте поставить DateTime.Now перед локом, сразу после лока, в конце сниппета, чтобы понять сколько времени тратится на вход в лок.
 
У вас сниппет для таблиц использует лок, а сниппет для списков нет.
Попробуйте поставить DateTime.Now перед локом, сразу после лока, в конце сниппета, чтобы понять сколько времени тратится на вход в лок.
так для списков лок и не нужен, а экшен "Добавить список в таблицу" имеет встроенный лок насколько я понял.
В зенно таблицы работают просто медленно, GetCell и SetCell, я вот сейчас на списках сделал и 5сек меня устраивает, это не критично.
 
так для списков лок и не нужен, а экшен "Добавить список в таблицу" имеет встроенный лок насколько я понял.
В зенно таблицы работают просто медленно, GetCell и SetCell, я вот сейчас на списках сделал и 5сек меня устраивает, это не критично.
Просто вы сравниваете, сниппеты для списка и для таблицы, и говорите, что время выполнения для списка гораздо быстрее.
 
Просто вы сравниваете, сниппеты для списка и для таблицы, и говорите, что время выполнения для списка гораздо быстрее.
Нет не так, Мне нужно обработать таблицу, и первый сниппет работает с таблицей, на это уходит ~30сек.
Поэтому мне приходится таблицу разбивать на списки, и обрабатывать списки, и потом обработанные списки класть в таблицу. И на это уходит ~5сек.
Т.е. результат у этих двух действий будет одинаковый. Так что таблицы работают в разы медленнее списков.
Т.е. в конечном результате в этих двух случаях, проект заканчивает работу сохранением обработанной таблицы в файл.
 
Последнее редактирование:

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