Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework
'и 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
Примеры к главе 10 (производительность и XML)
Листинг 10.1. Использование XML DOM для сохранения данных в файле и их загрузкиOption Strict On
Option Compare Binary
Imports System
'---------------------------------------------
'Демонстрирует сохранение и загрузку файлов с
'использованием объектной модели документа XML
'---------------------------------------------
Public Class SaveAndLoadXML_UseDOM
'XML-дескрипторы, которые мы будем использовать в нашем документе
Const XML_ROOT_TAG As String = "AllMyData"
Const XML_USERINFO_TAG As String = "UserInfo"
Const XML_USERID_TAG As String = "UserID"
Const XML_NAMEINFO_TAG As String = "Name"
Const XML_FIRSTNAME _TAG As String = "FirstName"
Const XML_LASTNAME_TAG As String = "LastName"
'--------------------------------------------------------------
'Загружает пользовательское состояние
' [in] fileName: Имя файла, используемого для сохранения данных
' [out] userId: Загруженный идентификатор пользователя
' [out] firstName: Загруженное имя пользователя
' [out] lastName: Загруженная фамилия пользователя
'--------------------------------------------------------------
Public Shared Sub XML_LoadUserInfo(ByVal fileName As String, _
ByRef userId As Integer, ByRef firstName As String, _
ByRef lastName As String)
'Начинаем с нулевых значений
userId = 0
firstName = ""
lastName = ""
'Предполагаем, что данные еще не загружены
Dim gotUserInfoData As Boolean = False
Dim xmlDocument As System.Xml.XmlDocument = _
New System.Xml.XmlDocument
xmlDocument.Load(fileName)
'Получить корневой узел
Dim rootElement As System.Xml.XmlElement
rootElement = _
CType(xmlDocument.ChildNodes(0), System.Xml.XmlElement)
'Убедиться в том, что корневой узел согласуется с ожидаемым текстом,
'ибо противное означает, что мы имеем дело с каким-то другим XML-файлом
If (rootElement.Name <> XML_ROOT_TAG) Then
Throw New Exception("Тип корневого узла не совпадает с ожидаемым!")
End If
'-----------------------------------------------------------
'Простой конечный автомат для итеративного обхода всех узлов
'-----------------------------------------------------------
Dim childOf_RootNode As System.Xml.XmlElement