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

Листинг 15.5. Класс IrDAFileReceive

Листинг 15.5. Класс IrDAFileReceive

//-------------------------------------------------------------------
//Обеспечивает прием файла через IrDA (инфракрасный порт).
//
//Этот класс НЕ является реентерабельным и не должен вызываться более
//чем одной функцией за один раз. Если необходимо иметь несколько
//сеансов связи через IR, это необходимо делать путем создания
//нескольких различных экземпляров данного класса.
//-------------------------------------------------------------------
public class IrDAFileReceive {
 private bool m_wasListenerStopped;
 private string m_IrDAServiceName;
 private string m_fileNameForDownload;
 private string m_errorDuringTransfer;
 private System.Net.Sockets.IrDAListener m_irListener;
 private ReceiveStatus m_ReceiveStatus;
 public string ErrorText {
  get {
   return m_errorDuringTransfer;
  }
 }
 //--------------------------
 //Различные состояния приема
 //--------------------------
 public enum ReceiveStatus {
  NotDone_SettingUp,
  NotDone_WaitingForSender,
  NotDone_Receiving,
  Done_Success,
  Done_Aborted,
  Done_ErrorOccured
 }
 //------------------------------
 // Возвращает состояние передачи
 //------------------------------
 public ReceiveStatus Status {
  get {
   //Обеспечить многопоточную безопасность для предотвращения
   //параллельного выполнения операций чтения/записи
   lock(this) {
    return m_ReceiveStatus;
   } //конец lock
  } //конец get
 } //конец свойства
 private void setStatus(ReceiveStatus newStatus) {
  //Обеспечить многопоточную безопасность для предотвращения
  //параллельного выполнения операций чтения/записи
  lock(this) {
   m_ReceiveStatus = newStatus;
  } //конец lock
 }
 //--------------------------------------------------
 // [in] filename: желаемое имя для входного файла IR
 //--------------------------------------------------
 public IrDAFileReceive(string filename, string irdaServiceName) {
  //Имя сокета IrDA, который мы хотим открыть
  m_IrDAServiceName = irdaServiceName;
  //Имя файла, в котором мы хотим сохранить полученные данные
  m_fileNameForDownload = filename;
 }
 //----------------------------------------------------------
 //Обеспечивает асинхронный прием файла через IR
 //
 // [in] filename: имя файла, в который осуществляется запись
 //----------------------------------------------------------
 public void WaitForIRFileDownloadAsync() {
  //Заметьте, что сейчас мы находимся в режиме подготовки
  setStatus(ReceiveStatus.NotDone_SettingUp);
  //-------------------
  //Создать новый поток
  //-------------------
  System.Threading.ThreadStart threadEntryPoint;
  threadEntryPoint =
   new System.Threading.ThreadStart(WaitForIRFileDownload);
  System.Threading.Thread newThread = new System.Threading.Thread(threadEntryPoint);
  //Запустить поток на выполнение
  newThread.Start();
 }
 //------------------------------------------
 //Открывает порт IR и ожидает загрузки файла
 //------------------------------------------
 public void WaitForIRFileDownload() {
  System.IO.Stream outputStream = null;
  System.Net.Sockets.IrDAClient irdaClient = null;
  System.IO.Stream irStreamIn = null;
  try {
   //=========================================================
   //Задать и загрузить файл!
   //=========================================================
   internal WaitForIRFileDownload(ref outputStream,ref irdaClient, ref irStreamIn);
  } catch
  //Поглотить любые возникающие ошибки
  {
   setStatus(ReceiveStatus.Done_ErrorOccured);
  }
  //=============================================
  //Освободить все ресурсы
  //=============================================
  //Закрыть наш входной поток
  if (irStreamIn != null) {
   try {
    irStreamIn.Close();
   } catch {} //Поглотить любые возникающие ошибки
  }
  //Закрытие клиента IrDA
  if (irdaClient != null) {
   try {
    irdaClient.Close();
   } catch {} //Поглотить любые возникающие ошибки
  }
  //Закрыть файл, в который осуществлялась запись
  if (outputStream != null) {
   try {
    outputStream.Close();
   } catch {} //Поглотить любые возникающие ошибки
  }
  //Закрыть прослушивающее устройство, если оно выполняется
  if (m_irListener != null) {
   //Установить первым, чтобы код, выполняющийся другим потоком,
   //был отменен, если он установлен
   m_wasListenerStopped = true;
   try {
    m_irListener.Stop();
   } catch {} //Поглотить любые возникающие ошибки
   m_irListener = null;
  }
 }
 private void internal_WaitForIRFileDownload(
  ref System.IO.Stream outputStream,
  ref System.Net.Sockets.IrDAClient irdaClient,
  ref System.IO.Stream irStreamIn) {
  //---------------------------------------------------------
  //Открыть входной файл для направления в него потока данных
  //---------------------------------------------------------
  outputStream = System.IO.File.Open(m_fileNameForDownload, System.IO.FileMode.Create);
  //==========================================
  //ОБНОВЛЕНИЕ СОСТОЯНИЯ
  //==========================================
  setStatus(ReceiveStatus.NotDone_WaitingForSender);
  //---------------------------------
  //Открыть прослушивающее устройство
//---------------------------------
  try {
   m_wasListenerStopped = false;
   m_irListener = new System.Net.Sockets.IrDAListener(m_IrDAServiceName);
   m_irListener.Start();
  } catch (System.Exception eListener) {
   m_errorDuringTransfer = "Error creating listener - " + eListener.Message;
   goto exit_sub_with_error;
  }
  //Проверить, не поступила ли команда отменить выполнение
  if (m_wasListenerStopped == true) {
   goto exit_sub_with abort;
  }
  //------------------
  //Принять соединение
//------------------
  try {
   //--------------------------------------------------------------------
   //Выполнение будет приостановлено здесь до тех пор, пока устройство не
   //начнет передавать информацию, или не будет остановлен объект
   //прослушивания, выполняющийся в другом потоке)
   //--------------------------------------------------------------------
   irdaClient = m_irListener.AcceptIrDAClient();
  } catch (System.Exception eClientAccept) {
   //Если прослушивание остановлено другим потоком, инициировавшим отмену
   //выполнения, будет сгенерировано исключение и управление будет
   //передано сюда.
   if (m_wasListenerStopped == true) {
    goto exit_sub_with_abort;
   }
   //Если прослушивание не было прекращено,
   //то произошло иное исключение. Обработать его.
   m_errorDuringTransfer = "Error accepting connection - " + eClientAccept.Message;
   goto exit sub_with error;
  }
  //B этом месте возможны два состояния:
  //#1: Мы получили соединение от передающего устройства IR
  //#2: IR-запрос был отменен (кто-то вызвал функцию STOP)
  // (в этом случае приведенный ниже код сгенерирует исключение)
  //Проверить, не было ли отменено выполнение
  if (m_wasListenerStopped == true) {
   goto exit_sub_with_abort;
  }
  //==========================================
  //ОБНОВЛЕНИЕ СОСТОЯНИЯ
  //==========================================
  setStatus(ReceiveStatus.NotDone_Receiving);
  //-------------------------
  //Открыть принимающий поток
  //-------------------------
  try {
   irStreamIn = irdaClient.GetStream();
  } catch (System.Exception exGetInputStream) {
   m_errorDuringTransfer = "Error getting input stream - " + exGetInputStream.Message;
   goto exit_sub_with_error;
  }
  //Приготовиться к получению данных!
  const int BUFFER_SIZE = 1024;
  byte[] inBuffer = new byte[BUFFER_SIZE];
  int bytesRead = 0;
  do {
   //Считать байты из порта IR
   bytesRead = irStreamIn.Read(inBuffer, 0, BUFFER_SIZE);
   //Записать байты в наш выходной поток
   if (bytesRead > 0) {
    outputStream.Write(inBuffer, 0, bytesRead);
   }
  } while (bytesRead > 0);
  outputStream.Flush(); //Закончить запись любых выходных данных
  //==========================================
  //ОБНОВЛЕНИЕ СОСТОЯНИЯ: УСПЕШНО ВЫПОЛНЕНО
  //==========================================
  setStatus(ReceiveStatus.Done_Success);
  return; //Ошибки отсутствуют
  //==========================================
  //ОШИБКА...
  //==========================================
exit_sub_with_abort:
  //ОБНОВЛЕНИЕ СОСТОЯНИЯ: Отменено (но не из-за ошибки)
  setStatus(ReceiveStatus.Done_Aborted);
  return;
exit_sub_with_error:
  //ОБНОВЛЕНИЕ СОСТОЯНИЯ: ОШИБКА!!!!
  setStatus(ReceiveStatus.Done_ErrorOccured);
 }
} //конец класса

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


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