Действия для инициализации проекта

famous1144

Client
Регистрация
27.03.2014
Сообщения
137
Благодарностей
53
Баллы
28
Очень хотелось бы видеть сабж. Конечно, можно и сейчас реализовать это какими-то костылями, но хотелось бы иметь для этого отдельную фичу. Как я это вижу:

1 вариант(простой):
Сделать метод, принимающий на вход функцию-замыкание.
Код:
project.SetInitCallback(() => {
    .............
});
2 вариант(более удобный):
Сделать доп. кружок, наподобие "Start" или "BadEnd", исполнение по которому пойдет только один раз, в самом начале.
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
Не понял зачем. Под инициализацией что понимаете?
 

famous1144

Client
Регистрация
27.03.2014
Сообщения
137
Благодарностей
53
Баллы
28
Под инициализацией что понимаете?
Любые действия, выполняемые один раз в самом начале выполнения задания, при любом кол-ве потоков. Например, сделать запрос к базе и взять оттуда список урлов, запустить тор-прокси, и т.д. Если делать это в каждом потоке, то запрос к базе будет выполнен много раз, вместо одного. Если проверять наличие/отсутствие файла и т.д., то все равно может так получиться, что ресурсоемкую операцию, нужную всего 1 раз, выполняет сразу 2 или более потоков. Сейчас у меня это решено с помощью батника, который эти действия и выполняет, а потом запускает задание. Но хотелось бы иметь возможность делать все это средствами самого Зеннопостера.
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
Глобальные переменные используйте. Проверяете значение переменной, если оно не 1, например, делаете глобальное действие и ставите в значение глобалки 1
Остальные потоки будут это пропускать.
 

famous1144

Client
Регистрация
27.03.2014
Сообщения
137
Благодарностей
53
Баллы
28
Глобальные переменные используйте. Проверяете значение переменной, если оно не 1, например, делаете глобальное действие и ставите в значение глобалки 1
Остальные потоки будут это пропускать.
Тут есть одна тонкость. Это решение хорошо работает, когда действие выполняется доли секунды. А если это долгая операция, высока вероятность, что либо 2 и более потоков начнут ее делать вместе, либо, если поставить значение переменой перед действием, данные для инициализации просто не будут вовремя получены. Я написал такое вот решение в виде макроса:
Код:
project.Context["RunOne"] = (Action<string, Action>)((Key, Funct) => {
    var NS = "НАШ_НЕЙМСПЕЙС";
    Func<string> Get = () => { return project.GlobalVariables[NS, Key].Value as string; };
    Action<string> Set = (Val) => project.GlobalVariables[NS, Key].Value = Val;
   
    // если еще ничего не делали
    if(Get() == "") {
        Set("process");
        try {
            Funct();
            Set("end");
        } catch(Exception e) {
            Set("");
            throw e;
        }
    }
   
    // если действие уже выполнется, ждем окончания
    while(Get() == "process") {
        System.Threading.Thread.Sleep(1000);
    }
});
Использование:
Код:
var Run = project.Context["RunOne"] as Action<string, Action>;
Run("MyVar", () => { // глобальная переменная MyVar должна быть создана и должна иметь пустое значение
     .................
});
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113

famous1144

Client
Регистрация
27.03.2014
Сообщения
137
Благодарностей
53
Баллы
28
Не знал, что есть переменная SyncObject. Очень удобно :-)
 

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