Книга: Программирование мобильных устройств на платформе .NET Compact Framework
Листинг 9.1. Код для управления выполнением одиночной задачи фоновым потоком
Листинг 9.1. Код для управления выполнением одиночной задачи фоновым потоком
using System;
public class ThreadExecuteTask {
//Перечисляем возможные состояния
public enum ProcessingState {
//-------------------
//Начальное состояние
//-------------------
//Пока ничего интересного не происходит
notYetStarted,
//-----------------
//Рабочие состояния
//-----------------
//Ожидание запуска фонового потока
waitingToStartAsync,
//Выполнение кода в фоновом потоке
running,
//Запросить отмену выполнения вычислений
requestAbort,
//--------------------
//Состояния завершения
//--------------------
//Состояние завершения: выполнение фонового потока
//успешно завершено
done,
//Состояние завершения: выполнение потока отменено
//до его завершения
aborted
}
ProcessingState m_processingState;
public delegate void ExecuteMeOnAnotherThread(ThreadExecuteTask checkForAborts);
private ExecuteMeOnAnotherThread m_CallFunction;
private object m_useForStateMachineLock;
public ThreadExecuteTask(ExecuteMeOnAnotherThread functionToCall) {
//Создать объект, который мы можем использовать
//в конечном автомате в целях блокировки
m_useForStateMachineLock = new Object();
//Обозначить готовность к началу выполнения
m_processingState = ProcessingState.notYetStarted;
//Сохранить функцию, которую необходимо вызвать
//в новом потоке
m_CallFunction = functionToCall;
//----------------------------------------------------------
//Создать новый поток и вызвать в нем функцию на выполнение:
// this.ThreadStartPoint()
//----------------------------------------------------------
System.Threading.ThreadStart threadStart;
threadStart = new System.Threading.ThreadStart(ThreadStartPoint);
System.Threading.Thread newThread;
newThread = new System.Threading.Thread(threadStart);
//Обозначить готовность к началу выполнения (в целях определенности
//это важно сделать еще до того, как будет запущен поток!)
setProcessingState(ProcessingState.waitingToStartAsync);
//Дать ОС команду начать выполнение нового потока в асинхронном режиме
newThread.Start();
//Возвратить управление функции, вызывающей этот поток
}
//---------------------------------------------
//Эта функция является точкой входа, вызываемой
//для выполнения в новом потоке
//---------------------------------------------
private void ThreadStartPoint() {
//Установить состояние обработки, соответствующее
//выполнению функции в новом потоке!
setProcessingState(ProcessingState.running);
//Запустить на выполнение пользовательский код и передать указатель в
//наш класс, чтобы этот код мог периодически проверять, не поступил ли
//запрос на прекращение выполнения
m_CallFunction(this);
//Если выполнение не было отменено, изменить состояние таким образом,
//чтобы оно соответствовало успешному завершению
if (m_processingState != ProcessingState.aborted) {
//Обозначить завершение выполнения
setProcessingState(ProcessingState.done);
}
//Выйти из потока...
}
//----------------
//Конечный автомат
//----------------
public void setProcessingState(ProcessingState nextState) {
//B любой момент времени только одному потоку выполнения
//могут быть разрешены попытки изменить состояние
lock(m_useForStateMachineLock) {
//B случае попытки повторного вхождения в текущее состояние
//никакие дополнительные действия не выполняются
if (m_processingState == nextState) {
return;
}
//------------------------------------------------------
//Простейший защитный код, гарантирующий
//невозможность перехода в другое состояние, если задача
//либо успешно завершена, либо успешно отменена
//------------------------------------------------------
if ((m_processingState == ProcessingState.aborted) ||
(m_processingState == ProcessingState.done)) {
return;
}
//Убедиться в допустимости данного изменения состояния
switch (nextState) {
case ProcessingState.notYetStarted:
throw new Exception("Переход в состояние 'notYetStarted' невозможен");
case ProcessingState.waitingToStartAsync:
if (m_processingState != ProcessingState.notYetStarted) {
throw new Exception("Недопустимое изменение состояния");
}
break;
case ProcessingState.running:
if (m_processingState != ProcessingState.waitingToStartAsync) {
throw new Exception("Недопустимое изменение состояния");
}
break;
case ProcessingState.done:
//Мы можем завершить работу лишь тогда, когда она выполняется.
//Это возможно также в тех случаях, когда пользователь затребовал
//отмену выполнения, но работа к этому моменту уже была закончена
if ((m_processingState != ProcessingState.running) &&
(m_processingState != ProcessingState.requestAbort)) {
throw new Exception("Недопустимое изменение состояния");
}
break;
case ProcessingState.aborted:
if (m_processingState != ProcessingState.requestAbort) {
throw new Exception("Недопустимое изменение состояния");
}
break;
}
//Разрешить изменение состояния
m_processingState = nextState;
}
}
public ProcessingState State {
get {
ProcessingState currentState;
//Предотвратить попытки одновременного чтения/записи состояния
lock(m_useForStateMachineLock) {
currentState = m_processingState;
}
return currentState;
}
}
} //Конец класса
В листинге 9.2 представлен код, имитирующий выполнение работы фоновым потоком. Когда фоновый поток начинает выполнять код, на экране отображается окно сообщения. Выполнение работы имитируется созданием серии пауз длительностью в одну треть секунды, в промежутках между которыми рабочий код проверяет, не поступил ли от другого потока запрос на прекращение выполнения.
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Основные "рычаги" управления производительностью
- Категорийный менеджмент. Курс управления ассортиментом в рознице
- Дополнительные национальные кодовые страницы и порядки сортировки
- Глава 5 Агрессивные формы кода и борьба с ними
- 1.1. Информатика. Предмет информатики. Основные задачи информатики
- Повторяющиеся задачи
- Постановка задачи
- Стиль написания исходного кода
- 1.4. Кодирование информации
- 1.4.1. Кодирование во время выполнения
- Три способа кодирования звука