KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Иво Салмре, "Программирование мобильных устройств на платформе .NET Compact Framework" бесплатно, без регистрации.
Перейти на страницу:

  //Рабочие состояния

  //-----------------

  //Ожидание запуска фонового потока

  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 представлен код, имитирующий выполнение работы фоновым потоком. Когда фоновый поток начинает выполнять код, на экране отображается окно сообщения. Выполнение работы имитируется созданием серии пауз длительностью в одну треть секунды, в промежутках между которыми рабочий код проверяет, не поступил ли от другого потока запрос на прекращение выполнения.

Листинг 9.2. Тестовая программа для выполнения работы в фоновом потоке

using System;

//-------------------------------------------------

//Тестовый код, который используется для выполнения

//фоновым потоком

//-------------------------------------------------

public class Test1 {

 public int m_loopX;

 //------------------------------------------------------------------

 //Функция, вызываемая фоновым потоком

 // [in] threadExecute: Класс, управляющий выполнением нашего потока.

 // Мы можем контролировать его для проверки

 // того, не следует ли прекратить вычисления

 //------------------------------------------------------------------

 public void ThreadEntryPoint(ThreadExecuteTask threadExecute) {

  //Это окно сообщений будет отображаться в контексте того потока,

  //в котором выполняется задача

  System.Windows.Forms.MessageBox.Show("Выполнение ТЕСТОВОГО ПОТОКА");

  //------

  //60 раз

  //------

  for (m_loopX = 0; m_loopX < 60; m_loopX++) {

   //Если затребована отмена выполнения, мы должны завершить задачу

   if (threadExecute.State == ThreadExecuteTask.ProcessingState.requestAbort) {

    threadExecute.setProcessingState(ThreadExecuteTask.ProcessingState.aborted);

    return;

   }

   //Имитировать выполнение работы: пауза 1/3 секунды

   System.Threading.Thread.Sleep(333);

  }

 }

} //Конец класса

В листинге 9.3 содержится код, который можно запустить на выполнение из основного потока пользовательского интерфейса с целью активизации и контроля фоновой обработки. Этот код не является независимым классом и должен помещаться в форму, с кнопками которой должны быть связаны события щелчков на кнопках.

Листинг 9.3. Код для запуска и тестирования приведенного выше тестового кода

//Класс, который будет управлять выполнением нового потока

private ThreadExecuteTask m_threadExecute;


//Класс, метод которого мы хотим выполнять в асинхронном режиме

Test1 m_testMe;


//----------------------------------------------------------

//Этот код должен быть запущен ранее другого кода, поскольку

//он запускает новый поток выполнения!

//

//Создать новый поток и обеспечить его выполнение

//----------------------------------------------------------

private void buttonStartAsyncExecution_Click(object sender, System.EventArgs e) {

 //Создать экземпляр класса, метод которого мы хотим вызвать

 //в другом потоке

 m_testMe = new Test1();

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*