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

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

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

Option Strict On
Imports System
Public Class FindNextPrimeNumber
'Перечисляем возможные состояния
Public Enum ProcessingState
 notYetStarted
 waitingToStartAsync
 lookingForPrime
 foundPrime
 requestAbort
 aborted
End Enum
Private m_startPoint As Long
Private m_NextHighestPrime As Long
'Поиск какого количества элементов выполнен?
Private m_comparisonsSoFar As Long
'Для какого элемента сейчас выполняется поиск простого числа?
Private m_CurrentNumberBeingExamined As Long
'Вызывается для обновления информации о состоянии выполнения
Public Sub getExecutionProgressInfo( _
 ByRef numberCalculationsSoFar As Long, _
 ByRef currentItemBeingLookedAt As Long)
 'ПРИМЕЧАНИЕ. Мы используем блокирование потока для уверенности в том,
 'что эти значения не считываются во время выполнения операции
 'их записи. Поскольку доступ к m_comparisonsSoFar
 'и m_CurrentNumberBeingExamined могут осуществлять
 'одновременно несколько потоков, любая выполняемая над ними
 'операция записи/считывания должна синхронизироваться с "блокировкой",
 'что будет гарантировать "атомарность" этих операций
 SyncLock (Me)
  numberCalculationsSoFar = m_comparisonsSoFar
  currentItemBeingLookedAt = m_CurrentNumberBeingExamined
 End SyncLock
End Sub
Private m_processingState As ProcessingState
'---------------------------
'Простейший конечный автомат
'---------------------------
Public Sub setProcessingState(ByVal nextState As _
 ProcessingState)
 'Простейший защитный код, гарантирующий
 'невозможность перехода в другое состояние, если задача
 'либо успешно завершена, либо успешно отменена
 If ((m_processingState = ProcessingState.aborted) _
  OrElse (m_processingState = ProcessingState.foundPrime)) Then
  Return
 End If
 'Разрешить изменение состояния
 m_processingState = nextState
End Sub
Public ReadOnly Property getProcessingState() As ProcessingState
 Get
  Return m_processingState
 End Get
End Property
'------------------------
'Возвращает простое число
'------------------------
Public Function getPrime() As Long
 If (m_processingState <> ProcessingState.foundPrime) Then
  Throw New Exception("Простое число еще не найдено!")
 End If
 Return m_NextHighestPrime
End Function
'Конструктор класса
Public Sub New(ByVal startPoint As Long)
 setProcessingState(ProcessingState.notYetStarted)
 m_startPoint = startPoint
End Sub
'-----------------------------------------------------------
'Создает новый рабочий поток, который будет вызывать функцию
'findNextHighestPrime()
'-----------------------------------------------------------
Public Sub findNextHighestPrime_Async()
 Dim threadStart As System.Threading.ThreadStart
 threadStart = _
  New System.Threading.ThreadStart(AddressOf _
  findNextHighestPrime)
 Dim newThread As System.Threading.Thread
 newThread = New System.Threading.Thread(threadStart)
 'Состояние должно отвечать, что поиск продолжается
 setProcessingState(ProcessingState.waitingToStartAsync)
 newThread.Start()
End Sub
'-------------------------------------------------------------
'Основной рабочий поток. Этот поток запускает поиск очередного
'простого числа и выполняется до тех пор, пока не произойдет
'одно из следующих двух событий:
' (а) найдено очередное простое число
' (b) от внешнего (по отношению к данному) потока поступила
' команда прекратить выполнение
'--------------------------------------------------------------
Public Sub findNextHighestPrime()
 'Если поступила команда прекратить выполнение, то поиск даже
 'не должен начинаться
 If (m_processingState = ProcessingState.requestAbort) Then
  GoTo finished_looking
 End If
 'Состояние должно отвечать, что поиск продолжается
 setProcessingState(ProcessingState.lookingForPrime)
 Dim currentItem As Long
 'Проверить, является ли число нечетным
 If ((m_startPoint And 1) = 1) Then
  'Число является нечетным, начать поиск со следующего нечетного числа
  currentItem = m_startPoint + 2
 Else
  'Число является четным, начать поиск со следующего нечетного числа
  currentItem = m_startPoint + 1
 End If
 'Приступить к поиску простого числа
 While (m_processingState = ProcessingState.lookingForPrime)
  'B случае нахождения простого числа, возвратить его
  If (isItemPrime(currentItem) = True) Then
   m_NextHighestPrime = currentItem
   'Обновить состояние
   setProcessingState(ProcessingState.foundPrime)
  End If
  currentItem = currentItem + 2
 End While
finished_looking:
 'Выход. К этому моменту либо от другого потока поступила
 'команда прекратить поиск, либо было найдено и записано
 'следующее наибольшее простое число
 'Если поступил запрос прекратить выполнение,
 'сообщить, что выполнение процесса прекращено
 If (m_processingState = ProcessingState.requestAbort) Then
  setProcessingState(ProcessingState.aborted)
 End If
End Sub
'Вспомогательная функция, которая проверяет, является
'ли число простым
Private Function isItemPrime(ByVal potentialPrime _
 As Long) As Boolean
 'Если число - четное, значит, оно не является простым
 If ((potentialPrime And 1) = 0) Then
  Return False
 End If
 'Продолжать поиск до тех пор, пока не будет превышено значение
 'квадратного корня из числа
 Dim end_point_of_search As Long end_point_of_search = _
  CLng(System.Math.Sqrt(potentialPrime)) + 1
 Dim current_test_item As Long = 3
 While (current_test_item <= end_point_of_search)
  '---------------------------------------------------------
  'Проверить, не поступила ли команда прекратить выполнение!
  '---------------------------------------------------------
  If (m_processingState <> ProcessingState.lookingForPrime) Then
   Return False
  End If
  'Если число делится без остатка,
  'значит, оно не является простым
  If (potentialPrime Mod current_test_item = 0) Then
   Return False
  End If
  'Увеличить число на два
  current_test_item = current test_item + 2
  '-------------------------------------
  'Увеличить число проверенных элементов
  '-------------------------------------
  'ПРИМЕЧАНИЕ. Мы используем блокирование потока для уверенности в том,
  'что эти значения не считываются во время выполнения операции
  'их записи. Поскольку доступ к m_comparisonsSoFar
  'и m_CurrentNumberBeingExamined могут осуществлять
  'одновременно несколько нитей, любая выполняемая над ними
  'операция записи/считывания должна синхронизироваться с "блокировкой",
  'что будет гарантировать "атомарность" этих операций
  SyncLock (Me)
   m_CurrentNumberBeingExamined = potentialPrime
   m_comparisonsSoFar = m_comparisonsSoFar + 1
  End SyncLock
 End While
 'Число является простым
 Return True
End Function
End Class

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


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