Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] - نسخه متنی

Ivo Salmre

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید











Chapter 5 (State Machines) Samples

Listing 5.1. Sample Code for State Machine for Multiple-Choice Game



Option Explicit On
Class MyStateMachineClass
Private Enum GameState
StartScreen
AskQuestion
CongratulateUser
ScoldUser
End Enum
Private m_CurrentGameState As GameState
'----------------------------------------------
'The state machine that drives our user interface
'and manages other application state based on the
'mode the user is currently in
'----------------------------------------------
Private Sub StateChangeForGame(ByVal newGameUIState _
As GameState)
'See which state the application is being brought into
Select Case (newGameUIState)
Case GameState.StartScreen
'If we are coming from a state that does not allow
'transition to this state, throw an exception
If ((m_CurrentGameState <> GameState.CongratulateUser) _
AndAlso (m_CurrentGameState <> GameState.ScoldUser)) Then
Throw New System.Exception("Illegal State Change!")
End If
'UNDONE: Place code here to
' 1. Hide, Show, Move UI controls into place
' 2. Set up what ever variables/game-state needed
' for this mode
'
' SetUpGameStateForStartScreen()
Case GameState.AskQuestion
'If we are coming from a state that does not allow
'transition to this state, throw an exception
If ((m_CurrentGameState <> GameState.StartScreen) _
AndAlso (m_CurrentGameState <> GameState.CongratulateUser) _
AndAlso (m_CurrentGameState <> GameState.ScoldUser)) Then
Throw New System.Exception("Illegal State Change!")
End If
'UNDONE: Place code here to
' 1. Hide, Show, Move UI controls into place
' 2. Set up what ever variables/game-state needed
' for this mode
'
' SetUpGameStateForAskQuestion()
Case GameState.CongratulateUser
'If we are coming from a state that does not allow
'transition to this state, throw an exception
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Illegal State Change!")
End If
'UNDONE: Place code here to
' 1. Hide, Show, Move UI controls into place
' 2. Set up what ever variables/game-state needed
' for this mode
'
' SetUpGameStateForCongratulateUser()
Case GameState.ScoldUser
'If we are coming from a state that does not allow
'transition to this state, throw an exception
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Illegal State Change!")
End If
'UNDONE: Place code here to
' 1. Hide, Show, Move UI controls into place
' 2. Set up what ever variables/game-state needed
' for this mode
'
' SetUpGameStateForScoldUser()
Case Else
Throw New System.Exception("Unknown state!")
End Select
'Store the new requested state as our current state
m_CurrentGameState = newGameUIState
End Sub
End Class

Listing 5.2. Application State Being Changed Implicitly (Bad Design!)



'Code that gets run when the form is loaded
Private Sub Form1_Load(ByVal sender As System.Object, ByVal _
e As System.EventArgs) Handles MyBase.Load
TextBox1.Visible = True
ListBox1.Visible = False
End Sub
'Data
Private m_someImportantInfo As String
'The user has clicked the button and wants to move on to the
'next step in this application. Hide the text box and show
'list box in its place.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal _
e As System.EventArgs) Handles Button1.Click
m_someImportantInfo = TextBox1.Text
TextBox1.Visible = False
ListBox1.Visible = True
End Sub

Listing 5.3. Application State Being Changed Explicitly (Good Design)



Private m_someImportantInfo As String
'Define the states the application can be in
Enum MyStates
step1
step2
End Enum
'------------------------------------------------------
'The central function that is called
'whenever the application state needs
'to be changed
'------------------------------------------------------
Sub ChangeApplicationState(ByVal newState As 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
'------------------------------------------------------
'The user has clicked the button and wants to move on to the
'next step in this application. Hide the text box and show
'list box in its place.
'------------------------------------------------------
Private Sub button1_Click(ByVal sender As Object, ByVal _
e As System.EventArgs)
'Call a central function to change the state
ChangeApplicationState(MyStates.step2)
End Sub
'------------------------------------------------------
'Code that gets run when the form is loaded
'------------------------------------------------------
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
'Call a central function to change the state
ChangeApplicationState(MyStates.step1)
End Sub

Listing 5.4. Code for the Background Thread Prime Number Calculator



Option Strict On
Imports System
Public Class FindNextPrimeNumber
'States we can be in.
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
'--------------------------------------------------
'A very simple state machine.
'--------------------------------------------------
Public Sub setProcessingState(ByVal nextState _
As ProcessingState)
'--------------------------------------------------
'Some very simple protective code to make sure
'we can't enter another state if we have either
'successfully finished, or successfully aborted
'--------------------------------------------------
Dim currentState As ProcessingState
currentState = getProcessingState()
If ((currentState = ProcessingState.aborted) _
OrElse (currentState = ProcessingState.foundPrime)) Then
Return
End If
'Thread concurrency protection
SyncLock (Me)
'Allow the state change
m_processingState = nextState
End SyncLock
End Sub
Public Function getProcessingState() As ProcessingState
Dim currentState As ProcessingState
'Thread concurrency protection
SyncLock (Me)
currentState = m_processingState
End SyncLock
Return currentState
End Function
Public Function getTickCountDelta() As Integer
If (getProcessingState() = _
ProcessingState.lookingForPrime) Then
Throw New Exception( _
"Still looking for prime! No final time calculated")
End If
Return m_endTickCount - m_startTickCount
End Function
'---------------------------------------------------
'Returns the prime
'---------------------------------------------------
Public Function getPrime() As Long
If (getProcessingState() <> ProcessingState.foundPrime) Then
Throw New Exception("Prime number not calculated yet!")
End If
Return m_NextHighestPrime
End Function
'Class constructor
Public Sub New(ByVal startPoint As Long)
setProcessingState(ProcessingState.notYetStarted)
m_startPoint = startPoint
End Sub
'------------------------------------------------------------
'Creates a new worker thread that will call
' "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)
'Set our processing state to say that we are looking
setProcessingState(ProcessingState.waitingToStartAsync)
newThread.Start()
End Sub
'------------------------------------------------------------
'This is the main worker function. This synchronously starts
'looking for the next prime number and does not exit until
'either:
' (a) The next prime is found
' (b) An external thread to this thread tells us to abort
'------------------------------------------------------------
Public Sub findNextHighestPrime()
'If we've been told to abort, don't even start looking
If (getProcessingState() = ProcessingState.requestAbort) Then
GoTo finished_looking
End If
'Set our processing state to say that we are looking
setProcessingState(ProcessingState.lookingForPrime)
m_startTickCount = System.Environment.TickCount
Dim currentItem As Long
'See if it's odd
If ((m_startPoint And 1) = 1) Then
'It's odd, start at the next odd number
currentItem = m_startPoint + 2
Else
'It's even, start at the next odd number
currentItem = m_startPoint + 1
End If
'Look for the prime item.
While (getProcessingState() = ProcessingState.lookingForPrime)
'If we found the prime item, return it
If (isItemPrime(currentItem) = True) Then
m_NextHighestPrime = currentItem
'Update our state
setProcessingState(ProcessingState.foundPrime)
End If
currentItem = currentItem + 2
End While
finished_looking:
'Exit. At this point we have either been
'told to abort the search by another thread, or
'we have found and recorded the next highest prime number
'Record the time
m_endTickCount = System.Environment.TickCount
'If an abort was requested, note that we have aborted
'the process.
If (getProcessingState() = ProcessingState.requestAbort) Then
setProcessingState(ProcessingState.aborted)
End If
End Sub
'Helper function that looks to see if a specific item
'is a prime number.
Private Function isItemPrime(ByVal potentialPrime _
As Long) As Boolean
'If it's even, it's not prime
If ((potentialPrime And 1) = 0) Then
Return False
End If
'We want to look up until just past the square root
'of the item
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)
'---------------------------------
'Check to make sure we have not been asked to abort!
'---------------------------------
If (getProcessingState() <> _
ProcessingState.lookingForPrime) Then
Return False
End If
'If the item is divisible without remainder,
'it is not prime
If (potentialPrime Mod current_test_item = 0) Then
Return False
End If
'advance by two
current_test_item = current_test_item + 2
End While
'The item is prime
Return True
End Function
End Class

Listing 5.5. Test Code to Call the Background Thread Prime Number Calculator Above



'------------------------------------------------------------
'Code to process the Click event of Button1 on the form
'
'Call the prime number function on this thread!
'(This will block the thread)
'------------------------------------------------------------
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim testItem As Long
testItem = System.Convert.ToInt64("123456789012345")
Dim nextPrimeFinder As FindNextPrimeNumber
nextPrimeFinder = New FindNextPrimeNumber(testItem)
nextPrimeFinder.findNextHighestPrime()
Dim nextHighestPrime As Long
nextHighestPrime = nextPrimeFinder.getPrime()
MsgBox(CStr(nextHighestPrime))
'How long did the caclulation take?
Dim calculation_time As Integer
calculation_time = nextPrimeFinder.getTickCountDelta()
MsgBox(CStr(calculation_time) + " ms")
End Sub
'------------------------------------------------------------
'Code to process the Click event of Button2 on the form
'
'Call the prime number function on another thread!
'(This will not
'block this thread)
'We will use a state machine to track the progress
'------------------------------------------------------------
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim testItem As Long
testItem = System.Convert.ToInt64("123456789012345")
Dim nextPrimeFinder As FindNextPrimeNumber
nextPrimeFinder = New FindNextPrimeNumber(testItem)
'------------------------------------
'Do the processing on another thread
'------------------------------------
nextPrimeFinder.findNextHighestPrime_Async()
'Go in a loop and wait until we either find the result
'or it is aborted
While ((nextPrimeFinder.getProcessingState() <> _
FindNextPrimeNumber.ProcessingState.foundPrime) _
And _
(nextPrimeFinder.getProcessingState() <> _
FindNextPrimeNumber.ProcessingState.aborted))
'TEST CODE ONLY:
'Show a message box, allow the user to dismiss it
'This will help pass the time!
MsgBox("Still Looking...Click OK")
'We could abort the search by calling:
'nextPrimeFinder.setProcessingState(
' FindNextPrimeNumber.ProcessingState.requestAbort)
End While
'If we aborted the search, exit gracefully
If (nextPrimeFinder.getProcessingState() = _
FindNextPrimeNumber.ProcessingState.aborted) Then
MsgBox("Search was aborted!")
Return
End If
Dim nextHighestPrime As Long
nextHighestPrime = nextPrimeFinder.getPrime()
MsgBox(CStr(nextHighestPrime))
'How long did the calculation take?
Dim calculation_time As Integer
calculation_time = nextPrimeFinder.getTickCountDelta()
MsgBox(CStr(calculation_time) + " ms")
End Sub


/ 159