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

Листинг 9.1. Код для управления выполнением одиночной задачи фоновым потоком

Листинг 9.1. Код для управления выполнением одиночной задачи фоновым потоком

Option Strict On
Imports System
Public Class ThreadExecuteTask
'Перечисляем возможные состояния
Public Enum ProcessingState
 '-------------------
 'Начальное состояние
 '-------------------
 'Перечисляем возможные состояния
  notYetStarted
 '-----------------
 'Рабочие состояния
 '-----------------
 'Ожидание запуска фонового потока
 waitingToStartAsync
 'Выполнение кода в фоновом потоке
 running
 'Запросить отмену выполнения вычислений
 requestAbort
 '--------------------
 'Состояния завершения
 '--------------------
 'Состояние завершения: выполнение фонового потока
 'успешно завершено
 done
 'Состояние завершения: выполнение потока отменено
 'до его завершения
 aborted
End Enum
Private m_processingState As ProcessingState
Public Delegate Sub ExecuteMeOnAnotherThread(_
 ByVal checkForAborts As ThreadExecuteTask)
Private m_CallFunction As ExecuteMeOnAnotherThread
Private m_useForStateMachineLock As Object
Public Sub New(ByVal functionToCall As ExecuteMeOnAnotherThread)
 'Создать объект, который мы можем использовать в конечном автомате
 'в целях блокировки
 m_useForStateMachineLock = New Object
 'Обозначить готовность к началу выполнения
 m_processingState = ProcessingState.notYetStarted
 'Сохранить функцию, которую необходимо вызвать
 'в новом потоке
 m CallFunction = functionToCall
 '----------------------------------------------------------
 'Создать новый поток и вызвать в нем функцию на выполнение:
 ' this.ThreadStartPoint()
 '----------------------------------------------------------
 Dim threadStart As System.Threading.ThreadStart threadStart = _
  New System.Threading.ThreadStart(AddressOf ThreadStartPoint)
 Dim newThread As System.Threading.Thread
 newThread = New System.Threading.Thread(threadStart)
 'Обозначить готовность к началу выполнения (в целях определенности
 'это важно сделать еще до того, как будет запущен поток!)
 setProcessingState(ProcessingState.waitingToStartAsync)
 'Дать ОС команду начать выполнение нового потока в асинхронном режиме
 newThread.Start()
 'Возвратить управление функции, вызывающей этот поток
End Sub
'-------------------------------------------------
'Эта функция является точкой входа, вызываемой для
'выполнения в новом потоке
'-------------------------------------------------
Private Sub ThreadStartPoint()
 'Установить состояние обработки, соответствующее выполнению
 'функции в новом потоке!
 setProcessingState(ProcessingState.running)
 'Запустить на выполнение пользовательский код и передать указатель в наш
 'класс, чтобы этот код мог периодически проверять, не поступил ли запрос
 'на прекращение выполнения
 m_CallFunction (Me)
 'Если выполнение не было отменено, изменить состояние таким образом,
 'чтобы оно соответствовало успешному завершению
 If (m_processingState <> ProcessingState.aborted) Then
  'Обозначить завершение выполнения
  setProcessingState(ProcessingState.done)
 End If
 'Выйти из потока...
End Sub
'----------------
'Конечный автомат
'----------------
Public Sub setProcessingState(ByVal nextState As _
 ProcessingState)
 'В любой момент времени только одному потоку выполнения могут быть
 'разрешены попытки изменить состояние
 SyncLock (m_useForStateMachineLock)
  'В случае попытки повторного вхождения в текущее состояние
  'никакие дополнительные действия не выполняются
  If (m_processingState = nextState) Then
   Return
  End If
  '-----------------------------------------------------------
  'Простейший защитный код, гарантирующий
  'невозможность перехода в другое состояние, если задача либо
  'успешно завершена, либо успешно отменена
  '-----------------------------------------------------------
  If ((m_processingState = ProcessingState.aborted) OrElse _
   (m_processingState = ProcessingState.done)) Then
   Return
  End If
  'Убедиться в допустимости данного изменения состояния
  Select Case (nextState)
  Case ProcessingState.notYetStarted
   Throw New Exception _
    ("Переход в состояние 'notYetStarted' невозможен")
  Case ProcessingState.waitingToStartAsync
   If (m_processingState <> ProcessingState.notYetStarted) Then
    Throw New Exception("Недопустимое изменение состояния")
   End If
  Case ProcessingState.running
   If (m_processingState <> _
    ProcessingState.waitingToStartAsync) Then
    Throw New Ехсерtion("Недопустимое изменение состояния")
   End If
  Case ProcessingState.done
   'Мы можем завершить работу лишь тогда, когда она выполняется.
   'Это возможно также в тех случаях, когда пользователь затребовал
   'отмену выполнения, но работа к этому моменту уже была закончена
   If ((m_processingState <> ProcessingState.running) AndAlso _
    (m_processingState <> ProcessingState.requestAbort)) Then
    Throw New Exception("Недопустимое изменение состояния")
   End If
  Case ProcessingState.aborted
   If (m_processingState <> ProcessingState.requestAbort) Then
    Throw New Exception("Недопустимое изменение состояния")
   End If
  End Select
  'Разрешить изменение состояния
  m_processingState = nextState
 End SyncLock
End Sub
Public ReadOnly Property State() As ProcessingState
 Get
  Dim currentState As ProcessingState
  'Предотвратить попытки одновременного чтения/записи состояния
  SyncLock (m_useForStateMachineLock)
   currentState = m_orocessingState
  End SyncLock
  Return currentState
 End Get
End Property
End Class

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


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