KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework

Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Иво Салмре, "Программирование мобильных устройств на платформе .NET Compact Framework" бесплатно, без регистрации.
Перейти на страницу:

  setProcessingState(ProcessingState.notYetStarted);

  m_startPoint = startPoint;

 }

 //------------------------------------------------------------

 // Создает новый рабочий поток, который будет вызывать функцию

 // "findNextHighestPrime()"

 //------------------------------------------------------------

 public void findNextHighestPrime_Async() {

  System.Threading.ThreadStart threadStart;

  threadStart =  new System.Threading.ThreadStart(findNextHighestPrime);

  System.Threading.Thread newThread;

  newThread = new System.Threading.Thread(threadStart);

  //Состояние должно отвечать, что поиск продолжается

  setProcessingState(ProcessingState.waitingToStartAsync);

  newThread.Start();

  //-----------------------------------------------------------------

  // Основной рабочий поток. Этот поток запускает поиск очередного

  // простого числа и выполняется до тех пор, пока не произойдет

  // одно из следующих двух событий:

  // (а) найдено очередное простое число

  // (b) от внешнего (по отношению к данному) потока поступила команда

  // прекратить выполнение

  //------------------------------------------------------------------

 public void findNextHighestPrime() {

  //Если поступила команда прекратить выполнение, то поиск

  //даже не должен начинаться

  if (getProcessingState() == ProcessingState.requestAbort) {

   goto finished_looking;

  }

  //Состояние должно отвечать, что поиск продолжается

  setProcessingState(ProcessingState.lookingForPrime);

  m_startTickCount = System.Environment.TickCount;

  long currentItem;

  //Проверить, является ли число нечетным

  if ((m_startPoint & 1) == 1) {

   //Число является нечетным, начать поиск со следующего нечетного числа

   currentItem = m_startPoint + 2;

  } else {

   //Число является четным, начать поиск со следующего нечетного числа

   currentItem = m_startPoint + 1;

  }

  //Приступить к поиску простого числа

  while(getProcessingState() == ProcessingState.lookingForPrime) {

   //B случае нахождения простого числа возвратить его

   if (isItemPrime(currentItem) == true) {

    m_NextHighestPrime = currentItem; //Обновить состояние

    setProcessingState(ProcessingState.foundPrime);

   }

   currentItem = currentItem + 2;

  }

finished_looking:

  //Выход. К этому моменту либо от другого потока поступила

  //команда прекратить поиск, либо было найдено и записано

  //следующее наибольшее простое число

  //Зафиксировать время

  m_endTickCount = System.Environment.TickCount;

  //Если поступил запрос прекратить выполнение,

  //сообщить, что выполнение процесса прекращено

  if (getProcessingState() == ProcessingState.requestAbort) {

   setProcessingState(ProcessingState.aborted);

  }

 }

 //Конец функции

 //Вспомогательная функция, которая проверяет, является

 //ли число простым

 private bool isItemPrime(long potentialPrime) {

  //Если число — четное, значит, оно не является простым

  if ((potentialPrime & 1) == 0) {

   return false;

  }

  //Продолжать поиск до тех пор, пока не будет превышено

  //значение квадратного корня из числа

  long end_point_of_search;

  end_point_of_search = (long) System.Math.Sqrt(potentialPrime) + 1;

  long current_test_item = 3;

  while (current_test_item <= end_point_of_search ) {

  //----------------------------------------------------------

  // Проверить, не поступила ли команда прекратить выполнение!

  //----------------------------------------------------------

  if (getProcessingState() != ProcessingState.lookingForPrime) {

   return false;

  }

  //Если число делится без остатка,

  //значит, оно не является простым

  if (potentialPrime % current_test_item == 0) {

   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 и генерация исключений значительно облегчат вам поиск тонких ошибок, избавив от возможной многочасовой работы по их устранению.

Использование конечных автоматов в играх

Конечные автоматы весьма удобно использовать в играх, в которых различные персонажи, перемещающиеся в области игры, могут действовать в различных режимах. Например, каждый персонаж может находиться в различных состояниях, соответствующих отдельным направлениям или характеру движения (персонаж обращен лицом влево или вправо, бежит вперед или назад, взбирается по лестнице, падает и тому подобное). Использование конечных автоматов с четко определенными правилами для каждого персонажа, определяющими возможные варианты его поведения в различных состояниях и допустимые переходы из одного состояния в другое, позволяет создавать сложные варианты поведения как персонажей, управляемых компьютером, так и персонажей, управляемых пользователем.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*