Выбрать главу

  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 ) {