return false;
}
//Увеличить число на два
current_test_item = current_test_item + 2;
}
//Число является простым return true;
}
} //конец класса
В листинге 5.5 содержится код, который может быть помещен в форму для тестирования приведенного выше алгоритма фоновой обработки.
Листинг 5.5. Тестовая программа, которая вызывает на выполнение приведенный выше код фонового потока, осуществляющего поиск простого числа
//-----------------------------------------------------------
// Код, обрабатывающий событие щелчка на кнопке Button1 формы
//
// Вызвать из этого потока функцию поиска простого числа!
// (Это приведет к блокированию потока)
//-----------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e) {
long testItem;
testItem = System.Convert.ToInt64("123456789012345");
FindNextPrimeNumber nextPrimeFinder;
nextPrimeFinder = new FindNextPrimeNumber(testItem);
nextPrimeFinder.findNextHighestPrime();
long nextHighestPrime;
nextHighestPrime = nextPrimeFinder.getPrime();
System.Windows.Forms.MessageBox.Show(System.Convert.ToString(nextHighestPrime));
//Сколько времени заняли вычисления?
int calculation_time;
calculation_time = nextPrimeFinder.getTickCountDelta();
System.Windows.Forms.MessageBox.Show(System.Convert.ToString(calculation_time) + " мс");
}
//------------------------------------------------------------------------
// Код, обрабатывающий событие щелчка на кнопке Button2 формы
//
// Вызвать функцию поиска простого числа из другого потока!
// (Данный поток блокироваться не будет)
// Для отслеживания состояния выполнения задачи используем конечный автомат
//-------------------------------------------------------------------------
private void button2_Click(object sender, System.EventArgs e) {
long testItem;
testItem = System.Convert.ToInt64("123456789012345");
FindNextPrimeNumber nextPrimeFinder;
nextPrimeFinder = new FindNextPrimeNumber(testItem);
//------------------------------------
// Выполнить обработку в другом потоке
//------------------------------------
nextPrimeFinder.findNextHighestPrime_Async();
//Войти в цикл и ожидать до тех пор, пока не будет найдено
//простое число или выполнение не будет прекращено
while ((nextPrimeFinder.getProcessingState() != FindNextPrimeNumber.ProcessingState.foundPrime) &&
(nextPrimeFinder.getProcessingState() != FindNextPrimeNumber.ProcessingState.aborted)) {
//ТОЛЬКО В ТЕСТОВОМ КОДЕ:
//Отобразить окно сообщений и предоставить пользователю
//возможность убрать его с экрана.
//Это позволяет организовать паузу!
System.Windows.Forms.MessageBox.Show("Поиск продолжается... Щелкните на кнопке OK");
//Мы могли бы прекратить поиск путем следующего вызова функции:
//nextPrimeFinder.setProcessingState(
// FindNextPrimeNumber.ProcessingState.requestAbort);
}
//Осуществить корректный выход в случае прекращения поиска
if (nextPrimeFinder.getProcessingState() == FindNextPrimeNumber.ProcessingState.aborted) {
System.Windows.Forms.MessageBox.Show("Поиск прекращен!");
return;
}
long nextHighestPrime;
nextHighestPrime = nextPrimeFinder.getPrime();
System.Windows.Forms.MessageBox.Show(System.Convert.ToString(nextHighestPrime));
//Сколько времени заняли вычисления?
int calculation_time;
calculation_time = nextPrimeFinder.getTickCountDelta();
System.Windows.Forms.MessageBox.Show(System.Convert.ToString(calculation_time) + " мс");
}
Для выполнения примера с использованием указанного в листинге начального числа (123456789012345) на моем эмуляторе Pocket РС требовалось от 10 до 20 секунд. Исследуйте зависимость времени вычислений от количества цифр в начальном числе. (Как правило, с увеличением количества цифр время вычислений увеличивается.)
НА ЗАМЕТКУ
Чтобы не усложнять пример, количество правил, используемых в функции управления переходом, было сознательно выбрано небольшим. В случае фактической реализации количество правил целесообразно увеличить, например, разрешая только допустимые переходы между состояниями, и вырабатывая исключения в непредвиденных ситуациях. Наличие жестких правил, регламентирующих возможность изменения состояния, оказывается очень полезным при поиске трудно обнаруживаемых ошибок, обусловленных выполнением кода сразу несколькими потоками. В подобных ситуациях процесс выполнения усложняется, так что введение надежных правил, осуществление проверок с помощью операторов ASSERT и генерация исключений значительно облегчат вам поиск тонких ошибок, избавив от возможной многочасовой работы по их устранению.
Использование конечных автоматов в играх
Конечные автоматы весьма удобно использовать в играх, в которых различные персонажи, перемещающиеся в области игры, могут действовать в различных режимах. Например, каждый персонаж может находиться в различных состояниях, соответствующих отдельным направлениям или характеру движения (персонаж обращен лицом влево или вправо, бежит вперед или назад, взбирается по лестнице, падает и тому подобное). Использование конечных автоматов с четко определенными правилами для каждого персонажа, определяющими возможные варианты его поведения в различных состояниях и допустимые переходы из одного состояния в другое, позволяет создавать сложные варианты поведения как персонажей, управляемых компьютером, так и персонажей, управляемых пользователем.
Читать дальше