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

Листинг 9.5. Код класса FindNextPrimeNumber.cs

Листинг 9.5. Код класса FindNextPrimeNumber.cs

using System;
public class FindNextPrimeNumber {
 //Перечисляем возможные состояния
 public enum ProcessingState {
  notYetStarted,
  waitingToStartAsync,
  lookingForPrime,
  foundPrime,
  requestAbort,
  aborted
 }
 long m_startPoint;
 long m_NextHighestPrime;
 //Поиск какого количества элементов выполнен?
 long m_comparisonsSoFar;
 //Для какого элемента сейчас выполняется поиск простого числа?
 long m_CurrentNumberBeingExamined;
 //Вызывается для обновления информации о состоянии выполнения
 public void getExecutionProgressInfo(out long numberCalculationsSoFar, out long currentItemBeingLookedAt) {
  //ПРИМЕЧАНИЕ. Мы используем блокирование потока для уверенности в том,
  //что эти значения не считываются во время выполнения операции
  //их записи. Поскольку доступ к m_comparisonsSoFar
  //и m_CurrentNumberBeingExamined могут осуществлять
  //одновременно несколько потоков, любая выполняемая над ними
  //операция записи/считывания должна синхронизироваться с "блокировкой",
  //что будет гарантировать "атомарность" этих операций
  lock (this) {
   numberCalculationsSoFar = m_comparisonsSoFar;
   currentItemBeingLookedAt = m_CurrentNumberBeingExamined;
  }
 }
 ProcessingState m_processingState;
 //---------------------------
 //Простейший конечный автомат
 //---------------------------
 public void setProcessingState(ProcessingState nextState) {
  //------------------------------------------------------
  //Простейший защитный код, гарантирующий
  //невозможность перехода в другое состояние, если задача
  //либо успешно завершена, либо успешно отменена
  //------------------------------------------------------
  if ((m_processingState == ProcessingState.aborted) ||
      (m_processingState == ProcessingState.foundPrime)) {
   return;
  }
  //Разрешить изменение состояния
  m_processingState = nextState;
 }
 public ProcessingState getProcessingState {
  get {return m_processingState;}
 }
 //------------------------
 //Возвращает простое число
 //------------------------
 public long getPrime() {
  if (m_processingState != 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 (m_processingState == ProcessingState.requestAbort) {
   goto finished_looking;
  }
  //Состояние должно отвечать, что поиск продолжается
  setProcessingState(ProcessingState.lookingForPrime);
  long currentItem;
  //Проверить, является ли число нечетным
  if ((m_startPoint & 1) == 1) {
   //Число является нечетным, начать поиск со следующего нечетного числа
   currentItem = m_startPoint + 2;
  } else {
   //Число является четным, начать поиск со следующего нечетного числа
   currentItem = m_startPoint + 1;
  }
  //Приступить к поиску простого числа
  while (m_processingState == ProcessingState.lookingForPrime) {
   //B случае нахождения простого числа возвратить его
   if (isItemPrime(currentItem) == true) {
    m_NextHighestPrime = currentItem; //Обновить состояние
    setProcessingState(ProcessingState.foundPrime);
   }
   currentItem = currentItem + 2;
  }
finished_looking:
  //Выход. К этому моменту либо от другого потока поступила
  //команда прекратить поиск, либо было найдено и записано
  //следующее наибольшее простое число
  //Если поступил запрос прекратить выполнение,
  //сообщить, что выполнение процесса прекращено
  if (m_processingState == 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 (m_processingState != ProcessingState.lookingForPrime) {
    return false;
   }
   //Если число делится без остатка,
   //значит, оно не является простым
   if (potentialPrime % current_test_item == 0) {
    return false;
   }
   //увеличить число на два
   current_test item = current_test_item + 2;
   //------------------------------------------
   //Увеличить количество проверенных элементов
   //------------------------------------------
   //ПРИМЕЧАНИЕ. Мы используем блокирование потока для уверенности в том,
   //что эти значения не считываются во время выполнения операции
   //их записи. Поскольку доступ к m_comparisonsSoFar
   //и m_CurrentNumberBeingExamined могут осуществлять
   //одновременно несколько потоков, любая выполняемая над ними
   //операция записи/считывания должна синхронизироваться с "блокировкой",
   //что будет гарантировать "атомарность" этих операций
   lock(this) {
    m_CurrentNumberBeingExamined = potentialPrime;
    m_comparisonsSoFar++;
   }
  }
  //Число является простым
  return true;
 } //Конец функции
} //Конец класса

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


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