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

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

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

  currentItem.ToString() + ". " +

  numberCalculationsToFar.ToString() +

  " calculations done for you so far!");

 // setCalculationStatusText("Вычисления продолжаются. Поиск в области: " +

 // currentItem.ToString() + ". " +

 // "Для вас выполнено " +

 // numberCalculationsToFar.ToString() +

 // " расчетов!");

}

Листинг 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;

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

} //Конец класса

Резюме 

Фоновые потоки, если только их правильно использовать, могут пригодиться вам для улучшения условий интерактивного взаимодействия конечного пользователя с мобильным приложением за счет повышения способности пользовательского интерфейса к отклику. Фоновые потоки необходимо использовать умеренно, для вполне конкретных целей и лишь в тех случаях, когда они могут помочь вам справиться с реальными трудностями, связанными с обеспечением приемлемых интерактивных свойств приложения, которые не могут быть разрешены при использовании высокоприоритетного потока. Лучше всего проектировать приложение на основе однопоточной модели, привлекая фоновую обработку лишь тогда, когда вы убеждены в ее необходимости.

При написании кода фоновых потоков и проектировании классов, к которым могут иметь доступ одновременно несколько потоков, следует проявлять особую осторожность. Весьма полезно тщательно документировать код приложения, явно указывая, к каким его фрагментам будут пытаться получить доступ одновременно несколько потоков, а к каким, что не менее важно, не будут. Постарайтесь, чтобы количество классов, функций, свойств и переменных-членов, которые должны совместно использоваться несколькими потоками, было как можно меньшим, и уделите повышенное внимание к проектированию, анализу, тестированию и документированию соответствующих фрагментов кода.

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