Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
' SetUpGameStateForStartScreen()
Case GameState.AskQuestion
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If ((m_CurrentGameState <> GameState.StartScreen) _
AndAlso (m_CurrentGameState <> GameState.CongratulateUser) _
AndAlso (m_CurrentGameState <> GameState.ScoldUser)) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
'
' SetUpGameStateForAskQuestion()
Case GameState.CongratulateUser
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
'
' SetUpGameStateForCongratulateUser()
Case GameState.ScoldUser
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
' SetUpGameStateForScoldUser()
Case Else
Throw New System.Exception("Наизвестное состояние!")
End Select
'Сохранить запрошенное новое состояние в качестве текущего
m_CurrentGameState = newGameUIState
End Sub
End Class
Листинг 5.2. Неявное изменение состояния приложения (неудачный подход)'Код, выполняющийся при загрузке формы
Private Sub Form1_Load(ByVal senderAs System.Object,ByVal _
e As System.EventArgs) Handles MyBase.Load
TextBox1.Visible = True
ListBox1.Visible = False
End Sub
'Данные
Private m_someImportantInfoAs String
'Пользователь щелкнул на кнопке и хочет перейти к выполнению
'следующего шага данного приложения. Скрыть текстовое окно и отобразить
'окно списка в отведенном для этого месте.
Private Sub Button1_Click(ByVal senderAs System.Object,ByVal _
e As System.EventArgs) Handles Button1.Click
m_someImportantInfo = TextBox1.Text
TextBox1.Visible = False
ListBox1.Visible =True
End Sub
Листинг 5.3. Явное изменение состояния приложения (удачный подход)Private m_someImportantInfo As String
'Определить состояния, в которых может находиться приложение
Enum MyStates
step1
step2
End Enum
'----------------------------------------------------
'Главная функция, которая
'вызывается всякий раз, когда возникает необходимость
'в изменении состояния приложения
'----------------------------------------------------
Sub ChangeApplicationState(ByVal newStateAs MyStates)
Select Case newState
Case MyStates.step1
TextBox1.Visible = True
ListBox1.Visible = False
Case MyStates.step2
m_someImportantInfo = TextBox1.Text
TextBox1.Visible = False
ListBox1.Visible = True
End Select
End Sub
'----------------------------------------------------------------------
'Пользователь щелкнул на кнопке и хочет перейти к выполнению
'следующего шага данного приложения. Скрыть текстовое окно и отобразить
'окно списка в отведенном для этого месте.
'----------------------------------------------------------------------
Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
'Вызвать главную функцию для изменения состояния
ChangeApplicationState(MyStates.step2)
End Sub
'-------------------------------------
'Код, выполняющийся при загрузке формы
'-------------------------------------
Private Sub Forml_Load(ByVal sender As Object, _
ByVal eAs System.EventArgs)
'Вызвать главную функцию для изменения состояния
ChangeApplicationState(MyStates.step1)
End Sub
Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потокомOption Strict On
Imports System
Public Class FindNextPrimeNumber
'Определить возможные состояния
Public Enum ProcessingState
notYetStarted
waitingToStartAsync
lookingForPrime
foundPrime
requestAbort
aborted
End Enum
Private m_startTickCount As Integer
Private m_endTickCount As Integer
Private m_startPoint As Long
Private m_NextHighestPrime As Long
Private m_processingState As ProcessingState
'---------------------------
'Простейший конечный автомат
'---------------------------
Public Sub setProcessingState(ByVal nextState As ProcessingState)
'------------------------------------------------------------
'Простейший защитный код, гарантирующий
'невозможность перехода в другое состояние в случае успешного
'завершения задачи или успешной отмены ее выполнения
'------------------------------------------------------------
Dim currentState As ProcessingState
currentState = getProcessingState()
If ((currentState = ProcessingState.aborted) _
OrElse (currentState = ProcessingState.foundPrime)) Then
Return
End If
'Безопасное параллельное выполнение потоков
SyncLock (Me)
'Разрешить изменение состояния
m_processingState = nextState
End SyncLock
End Sub
Public Function getProcessingState() As ProcessingState
Dim currentState As ProcessingState
'Безопасное параллельное выполнение потоков
SyncLock (Me)
currentState = m_processingState
End SyncLock
Return currentState
End Function
Public Function getTickCountDelta() As Integer
If (getProcessingState() = _
ProcessingState.lookingForPrime) Then
Throw New Exception( _
"Продолжается поиск простого числа! Окончательное время еще не вычислено")
End If
Return m_endTickCount - m_startTickCount
End Function
'------------------------
'Возвращает простое число
'------------------------
Public Function getPrime() As Long
If (getProcessingState() <> 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 threadStartAs 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()
'Если поступила команда прекратить выполнение, то поиск даже