Программирование мобильных устройств на платформе .NET Compact Framework - Иво Салмре
Шрифт:
Интервал:
Закладка:
Если вы попытаетесь создать сокет IrDA или соединиться с ним при помощи кода, выполняющегося на эмуляторах Pocket PC, смартфона или Windows СЕ, то, вероятнее всего, в процессе выполнения вашего приложения сгенерируется исключение. Это означает, что, в отличие от большинства других средств .NET Compact Framework, проектировать и тестировать код для IrDA следует с использованием реального физического устройства. Хотя эта трудность и не является непреодолимой, процесс проектирования и тестирования приложения из-за этого усложняется, поскольку для тестирования кода, обеспечивающего работу с IrDA, вам потребуется два физических устройства, одно из которых действует в качестве IrDA-сервера, а второе — IrDA-клиента. Вследствие этой дополнительной сложности код для обмена данными через IrDA рекомендуется писать и тестировать отдельно от остальной части приложения с использованием максимально упрощенной модели приложения, чтобы исключить любые возможные просчеты в организации процесса передачи данных. После устранения всех возможных неполадок из кода, обеспечивающего работу с IrDA, его можно будет перенести в полную версию приложения.
Листинг 15.3. Тестовый код, который необходимо поместить в класс формы для тестирования передачи и приема данных посредством механизма IrDA//Имя, которое мы хотим присвоить сокету IrDA
const string myIrDASocketName = "IrDaTestFileTransmit";
private void buttonTestFileSend_Click(object sender, System.EventArgs e) {
//Создать простой текстовый файл, который мы хотим передать
const string fileName = "\myTestSendFile.txt";
System.IO.StreamWriter textFileStream;
textFileStream = System.IO.File.CreateText(fileName);
textFileStream.WriteLine("Today...");
textFileStream.WriteLine("is а nice day");
textFileStream.WriteLine("to go swim");
textFileStream.WriteLine("in the lake");
textFileStream.Close(); IrDAFileSend irdaFileSend;
irdaFileSend = new IrDAFileSend(fileName, myIrDASocketName);
//Имеется 2 режима: 1 — Sync (синхронный), 2 — Async (асинхронный)
//1. Вызвать функцию в синхронном режиме
//и блокировать поток выполнения до тех пор,
//пока файл не будет передан
//1a. Вызвать функцию в синхронном режиме
//и блокировать поток выполнения до тех пор,
//пока файл не будет передан
this.Text = "Trying to send...";
//1b. Подождать, пока клиент не будет найден, а затем передать файл
irdaFileSend.LoopAndAttemptIRSend();
//1c. Информировать пользователя о том, что файл передан
System.Windows.Forms.MessageBox.Show("File sent!");
this.Text = "IrDA: Sent!";
//2. Вызвать функцию в асинхронном режиме и поручить
//передачу файла фоновому потоку
//irdaFileSend.LoopAndAttemptIRSendAsync();
//ПРИМЕЧАНИЕ: Если мы вызываем функцию в асинхронном режиме, то должны
//периодически проверять, не завершила ли она выполнение, путем
//вызова метода 'irdaFileSend.Status'
}
private void buttonTestFileReceive_Click(object sender, System.EventArgs e) {
//Если файл назначения уже существует, уничтожить его
const string fileName = "\myTestReceiveFile.txt";
if (System.IO.File.Exists(fileName)) {
System.IO.File.Delete(fileName);
}
IrDAFileReceive irdaFileReceive;
irdaFileReceive = new IrDAFileReceive(fileName, myIrDASocketName);
//Имеется 2 режима: 1 - Sync (синхронный), 2 — Async (асинхронный)
//1. Вызвать функцию в синхронном режиме
//и блокировать поток выполнения до тех пор,
//пока файл не будет получен
//1a. Информировать пользователя о том, что мы ожидаем получения файла
this.Text = "Waiting to receive...";
//1b. Ожидать, пока не будет сделана попытка установления с нами связи
//и передачи файла
irdaFileReceive.WaitForIRFileDownload();
//1c. Информировать пользователя о том, что мы получили переданный файл
this.Text = "IrDA: received!";
System.Windows.Forms.MessageBox.Show("File received!");
//2. Вызвать функцию в асинхронном режиме и поручить
//получение файла фоновому потоку
//irdaFileReceive.WaitForIRFileDownloadAsync();
//ПРИМЕЧАНИЕ: Если мы вызываем функцию в асинхронном режиме, то должны
//периодически проверять, не завершила ли она выполнение, путем
//вызова метода 'irdaFileReceive.Status'
}
Листинг 15.4. Класс IrDAIrDAFileSend//====================================================================
//Этот класс является клиентом IrDA. Он осуществляет поиск сервера
//IrDA, имя которого совпадает с именем службы IrDA, и после того, как
//он найден, направляет ему поток данных файла.
//====================================================================
class IrDAFileSend {
private string m_descriptionOfLastSendAttempt;
private string m_IrDAServiceName;
private string m_fileToSend;
private bool m_wasSenderStopped;
public enum SendStatus {
AttemptingToSend,
Finished_Successfully,
Finished_Aborted,
Finished_Error
}
private SendStatus m_SendStatus;
public SendStatus Status {
get {
//Блокировка выполнения параллельных операций чтения/записи в m_SendStatus
lock(this) {return m_SendStatus;}
}
}
private void setStatus(SendStatus newStatus) {
//Блокировка выполнения параллельных операций чтения/записи в m_SendStatus
lock(this) {m_SendStatus = newStatus;}
}
public string ErrorText {
get {return m_descriptionOfLastSendAttempt;}
}
//-----------
//КОНСТРУКТОР
//-----------
public IrDAFileSend(string fileToSend,string irdaServiceName) {
//Имя сокета IrDA, поиск которого мы хотим осуществить
m_IrDAServiceName = irdaServiceName;
//Файл, который мы хотим передать
m_fileToSend = fileToSend;
}
//--------------------------------------------------------------
//Запускает новый поток для осуществления попытки отправки файла
//--------------------------------------------------------------
public void LoopAndAttemptIRSendAsync() {
//Мы находимся в режиме передачи
setStatus(SendStatus.AttemptingToSend);
//Пользователь пока что не отменил выполнение операции
m_wasSenderStopped = false;
//Это функция, которую должен запустить на выполнение новый поток
System.Threading.ThreadStart threadEntryPoint;
threadEntryPoint = new System.Threading.ThreadStart(LoopAndAttemptIRSend);
//-----------------------------------
//Создать новый поток и запустить его
//-----------------------------------
System.Threading.Thread newThread = new System.Threading.Thread(threadEntryPoint);
newThread.Start(); //Вперед!
}
//-----------------------------------------------------
//Входит в цикл и пытается передать файл посредством IR
//-----------------------------------------------------
public void LoopAndAttemptIRSend() {
System.Net.Sockets.IrDAClient irDASender;
System.IO.Stream streamOutToIrDA;
System.IO.Stream streamInFromFile;
//Пользователь пока что не отменил выполнение операции
m_wasSenderStopped = false;
setStatus(SendStatus.AttemptingToSend);
//-----------------------------------------------------------------
//Непрерывное выполнение цикла, пока не удастся отправить сообщение
//-----------------------------------------------------------------
while(true) {
//Значения всех этих переменных должны быть нулевыми до и после
//вызова 'sendStream(...)', если не было сгенерировано исключение!
irDASender = null;
streamOutToIrDA = null;
streamInFromFile = null;
//Попытаться передать поток
bool bSuccess;
try {
bSuccess = sendStream(
out m_descriptionOfLastSendAttempt, ref streamOutToIrDA,
ref irDASender, ref streamInFromFile);
} catch (System.Exception eUnexpected) //Неожиданная ошибка!!!
{
setStatus(SendStatus.Finished_Error); //Отметить возникновение сбоя
m_descriptionOfLastSendAttempt =
"Unexpected error in IR send loop. " + eUnexpected.Message;
//------------------------------------------------
//Освободить все распределенные нами ранее ресурсы
//------------------------------------------------
if (streamOutToIrDA != null) {
try {
streamOutToIrDA.Close();
} саtch{};//Поглотить любую ошибку
streamOutToIrDA = null;
}
if (streamInFromFile != null) {
try {
streamInFromFile.Close();