скрытые фичи 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(), указав время приостановки процесса. |