Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #71, ОКТЯБРЬ 2006 г.

скрытые фичи C#

ДРОЗДОВ АНДРЕЙ AKA SULVERUS

Спецвыпуск: Хакер, номер #071, стр. 071-076-3


public static delegate play(string file_position);

public static delegate pause(string file_position);

MulticastDelegate Play_and_Stop = play+pause;

[события давно минувших дней.]

Вернемся к описанию кода нашего брутфорса: в нем я упоминал о событиях. События были и в С++, но теперь они строятся на основе делегатов. То есть мы «вешаем» событие на нужный нам делегат, и они передают методу нужные параметры. В нашем коде есть два события: NewMessage() и BruteComplete(). Первое событие находит делегат метода msg(), который вызывает метод, созданный для того, чтобы выводить в консоль сообщение; второе наступает в случае, если перебор был удачным. Если посмотреть событие дизассемблером (не обычным, а NET'овским), то мы увидим, что оно состоит из двух методов: add_[Имя События]() и remove_[Имя События](). Для того чтобы параметры не ушли «в никуда», мы должны создать приемники событий, которые будут ожидать их наступления. Что должен делать приемник? Он должен добавить принимающий метод в таблицу указателей делегата. Для этого нужно использовать перегруженный оператор «+=», а для удаления «-=». Добавим два приемника для делегатов каждой функции:

bug.NewMessage += new bug.msg_sender(bug.msg);

bug.BruteComplete += new bug.bOK(bug.BruteOk);

Теперь вместо того, чтобы писать полный адрес функции, можно просто писать NewMessage(string msg_text);. Для нашего брутфорса нам понадобится написать метод, который будет включать и выключать приемники событий:

переключатель событий

public static void EventSwitch(bool current_switch)

{

if (current_switch == true)

{

bug.NewMessage += new bug.msg_sender(bug.msg); //включаем приемники

bug.BruteComplete += new bug.bOK(bug.BruteOk);

}

else if (current_switch == false)

{

bug.NewMessage -= new bug.msg_sender(bug.msg); //выключаем приемники

bug.BruteComplete -= new bug.bOK(bug.BruteOk);

}

}

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

[о жизненных потоках.]

Рассказывая об особенностях программирования на C#, нельзя не упомянуть о потоках. Для работы с потоками существует пространство имен System.Threading. Для примера мы можем написать программу, которая будет считать числа, а для закрепления пройденного материала мы будем делать это не просто с помощью цикла for, но и используя перегрузку операторов квадратных скобок («[]»). Прежде чем создавать поток, нам нужно написать функцию для работы с числами. В данном случае мы будем использовать метод индексации (это и есть перегрузка операторов квадратных скобок):

обращение к элементам массива

for (i = 0; i < indexInt.Length; i++)

{

if (indexInt[i] < 10) //обращаемся к каждому элементу массива

NewMessage("Level1: " + indexInt[i].ToString());

else if (indexInt[i] < 20)

NewMessage("Level2: " + indexInt[i].ToString());

}

Используя перегрузку операторов квадратных скобок, мы проверяем каждый элемент числового массива, а для вывода в консоль результатов мы используем созданное нами ранее событие NewMessage(). Таким же способом можно обращаться не только к элементам массива, но и к элементам объекта. Теперь займемся потоками. Для создания потока надо объявить переменную типа Thread и указать, какую функцию мы будем загружать в поток: Thread counter = new Thread(new ThreadStart(bug.Index()));. Теперь мы можем запустить тот поток при помощи метода Thread.Start(). Для того чтобы не потерять наш поток, ему надо присвоить имя: надо заполнить параметр Thread.Name, далее можно прописать приоритет потока в параметре Thread.Priority. Заметим, что во время выполнения приложения наша функция опередит брутфорс, поскольку поток выполняется в фоновом режиме. Для того чтобы приостановить процесс, нужно использовать метод Thread.Sleep(), указав время приостановки процесса.

Назад на стр. 071-076-2  Содержание  Вперед на стр. 071-076-4