Описание работы ViKing.ApplicationFramework

Описание работы ViKing.ApplicationFramework

Давайте теперь разберемся в работе ViKing.ApplicationFramework более детально. В этой статья я попытался подробно описать работу фреймворка, поэтому статье получилось скучной и похожей на документацию. Тем не менее рекомендую ее прочитать, чтобы понять как все работает.

Основные функции

Основной класс Job состоит из нескольких функций (для использования их нужно перегрузить):

  • StartWork
  • DoWork
  • FinishWork

Вот что происходит при нажатии кнопки старт:

  • Создается новый инстанс класса Job
  • Инициализируются все поля
  • Выполняется конструктор класса (нам он не понадобится)
  • Выполняется функция StartJob
  • Запускается цикл, который бесконечно создает потоки (сколько задано пользователем) и выполняет на них функцию DoWork, до тех пор, пока не будет вызвана функция StopJob или юзер нажмет на стоп. Кнопка HardStop в интерфейсе вызывает Thread.Abort на всех потоках
  • После этого новые потоки не запускаются и фреймворк ждет, когда старые закончат выполняться
  • После этого вызывается функция FinishWork, в которой можно обработать и сохранить результат работы. Она будет вызвана даже если пользователь отменил выполнение задания

Также есть функции ApplicationStartup и ApplicationShutdown, которые выполняются при запуске и закрытии приложения.

Настройки

Для задания пользовательских данных используются публичные статические свойства. Для всех таких свойств будут сгенерированы элементы интерфейса. Их значения автоматически сохраняются в реестре, а отображение в интерфейсе можно контролировать с помощью атрибута PropertyDescription. Например

[PropertyDescription(Caption="Enter text", DefaultValue="example")]
public static string Prop { get; set; }

Для хранения текущего состояния задачи рекомендую использовать локальные поля и инициализировать их сразу при описании.

private ResourceManager<string> links = new ResourceManager<string>("links");

Во фреймворке есть свойства GlobalCookies и ThreadCookies. Эти куки подставляются в каждый запрос, сделанный функцией Request, если в ней явно не указан другой контейнер с куками. GlobalCookies общие для всех потоков, а ThreadCookies для каждого потока свои. То же самое и с проксями GlobalProxy и ThreadProxy.

Дополнительные инструменты

При работе с прокси рекомендую пользоваться встроенным менеджером. Для его включения нужно повесить атрибут [GuiSettings(UseProxies=true)] к классу Job. Он автоматически создаст необходимые элементы интерфейса, инициализирует ProxyManager, и будет выдавать каждому потоку в DoWork новый ThreadProxy. Если на потоке возникает ошибка, то она приписывается к текущему прокси. Если у сервера много ошибок, то он выкидывается из менеджера.

Аналогичным образом включается antigate. Добавляем [GuiSettings(UseAntigate=true)], если нужно включить антигейт и прокси, все записывается в одном атрибуте. Разгадывать капчу нужно с помощью функции PostCaptcha, при выключенном антигейте она просто будет выдавать окно с капчей пользователю.

Пример их использования есть в статье регер почты Rambler в 15 строк кода.

Списки и статистика

При выполнении задания юзеру показывается статистика. Показывать ее можно с помощью объекта Stats, например Stats[“accounts”]++, инициализировать ничего не надо.

Для записи файлов удобно использовать FileWriter. Он сам следит за статсами и удобен в работе:

FileWriter w = new FileWriter("file");
w.AppendLine("test");

При указании имени файла автоматически добавляется расширение .txt (если его нет). В статистике будет отображаться количество записанных строк.

Для чтения используется ResourceManager<T>. Остановимся на нем подробнее. Этот класс представляет из себя потокобезопасную очередь. Для инициализации используется конструктор, в который передается список объектов либо имя файла, имя статсов (если не указано будет совпадать с именем файла) и следует ли останавливать задание если список пуст. Для удобства у всех коллекций IEnumerable есть метод ToResourceManager(). Вытаскиваются из списка объекты с помощью метода Pop, а с помощью метода Push можно запихать их обратно.

Если вы хотите создать хитрую очередь (например циклическую), это тоже можно сделать, подписавшись на событие ItemPopping. В него передается очередной элемент и хэндлер должен решить, стоит ли его возвращать и стоит ли удалять. Если элемент не возвращается, то ResourceManager перейдет к следующему элементу. Например для менеджера проксей:

ResourceManager<ProxyWithStats> m = new ResourceManager<ProxyWithStats>();
m.InsertTakenToEnd = true;
m.ItemPopping += (o, e) =>
{
    e.Take = e.Item.ErrorsCount < ProxyWithStats.MaxErrors;
    e.Remove = !e.Take;
};

При вызове m.Pop хэндлер либо вернет первый прокси, либо удалит его из списка и попробует вернуть следующий (либо коллекция окажется пустой). Что если вы не возвращаете элемент, то удалять его необязательно и наоборот, можно удалять возвращенные элементы.

На этом пока все, рекомендую посмотреть пару более практических статей по фреймворку и попробовать что-то сделать самому.

Comments are closed.