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

Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потоком 

Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потоком 

using System;
public class FindNextPrimeNumber
{

 //Определить возможные состояния
 public enum ProcessingState {
  notYetStarted,
  waitingToStartAsync,
  lookingForPrime,
  foundPrime,
  requestAbort,
  aborted
 }
 int m_startTickCount;
 int m_endTickCount;
 long m_startPoint;
 long m NextHighestPrime;
 ProcessingState m_processingState;
 //---------------------------
 //Простейший конечный автомат
 //---------------------------
 public void setProcessingState(ProcessingState nextState) {
  //-----------------------------------------------------
  // Простейший защитный код, гарантирующий невозможность
  // перехода в другое состояние в случае успешного
  // завершения задачи или успешной отмены ее выполнения
  //-----------------------------------------------------
  if ((m_processingState == ProcessingState.aborted) || (m_processingState == ProcessingState.foundPrime)) {
   return;
  }
  //Разрешить изменение состояния
  lock(this) {
   m_processingState = nextState;
  }
 }
 public ProcessingState getProcessingState() {
  ProcessingState currentState; //Безопасное выполнение потока
  lock(this) {
   currentState = m_processingState;
  }
  return currentState;
 }
 public int getTickCountDelta() {
  if (getProcessingState() == ProcessingState.lookingForPrime) {
   throw new Exception("Продолжается поиск простого числа! Окончательное время еще не вычислено");
  }
  return m_endTickCount - m_startTickCount;
 }
 //-------------------------
 // Возвращает простое число
 //-------------------------
 public long getPrime() {
  if (getProcessingState() != ProcessingState.foundPrime) {
   throw new Exception("простое число еще не найдено!");
  }
  return m_NextHighestPrime;
 }
 //Конструктор класса
 public FindNextPrimeNumber(long startPoint) {
  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 содержится код, который может быть помещен в форму для тестирования приведенного выше алгоритма фоновой обработки.

Оглавление книги


Генерация: 1.098. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз