Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"
Автор книги: Иво Салмре
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 62 (всего у книги 69 страниц)
Для .NET Compact Framework существует много активных форумов, действующих по принципу "спрашивайте – ответим". Доступ к ним можно получить либо с помощью программы для работы с группами новостей, либо через Web-сайт http://msdn.microsoft.com/newsgroups/.
Можно указать еще несколько форумов, посвященных данной тематике:
■ microsoft.public.dotnet.framework.compactframework
■ microsoft.public.pocketpc.developer
■ microsoft.public.pocketpc.developer.networking
■ microsoft.public.smartphone.developer
Как и в случае любого форума или обсуждения, вопросы и ответы, которые вы встретите там, могут быть как интересными, так и не представляющими никакого интереса. Форумы – великолепное место для поиска подсказок и идей, которые помогут вам преодолеть проблемы, тормозящие дальнейшую работу, но там вы найдете исключительно информацию, которая предоставляется "без обещания компенсации возможного ущерба и без гарантий достоверности".
Общие вопросы разработки мобильных приложенийСамые последние замечательные новости о .NET Compact Framework и других технологиях разработки мобильного программного обеспечения, используемых компанией Microsoft, появляются на следующих Web-сайтах:
http://msdn.microsoft.com/mobility/
http://msdn.microsoft.com/mobility/prodtechinfo/devtools/netcf/faq/default.aspx
Для разработки приложений Microsoft Smartphone с использованием Visual Studio Net 2003 вам потребуется установить пакет SDK для Windows Mobile 2003-based Smartphones, доступный для загрузки по следующему адресу:
http://msdn.microsoft.com/mobility/windowsmobile/downloads/
Для просмотра постоянно обновляемого документа Wiki, содержащего ответы на наиболее часто задаваемые вопросы, посетите следующий сайт:
http://wiki.opennetcf.org/ow.asp?CompactFrameworkFAQ
Особенности взаимодействия с собственным кодомВызов собственного кода (native code) из VB.NET или C# не представляет особых сложностей, но вам следует знать о некоторых частных правилах и устоявшихся приемах. Лучше всего изучать это на примерах.
■ Основы работы с собственными кодами в среде .NET Compact Framework
An Introduction to P/Invoke and Marshalling on the Microsoft .NET Compact Framework
Авторы: Jon Box, Dan Fox; Quilogy
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/netcfintrointerp.asp
■ Тонкости работы с собственными кодами в среде .NET Compact Framework
Advanced P/Invoke on the Microsoft .NET Compact Framework
Авторы: Jon Box, Dan Fox; Quilogy
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/netcfadvinterop.asp
■ Передача асинхронных сообщений из собственного кода в управляемый код при помощи .NET Compact Framework
Asynchronous Callbacks from Native Win32 Code Автор: Maarten Struys; PTS Software
http://msdn.microsoft.corn/library/default.asp?url=/library/en-us/dnnetcomp/html/AsynchCallbacks.asp
Работа с операторами мобильных сетейКомпания Microsoft предлагает рекомендации и программу сотрудничества по вопросам создания, сертификации и развертывания приложений на мобильных телефонах, публикуемые операторами мобильных сетей.
■ Сокращенная ссылка, которая переадресует вас на более подробное содержимое, указанное далее:
Сокращенный URL-адрес Mobile2Market
http://www.mobile2market.com
■ Сертификация от Mobile2Market и маркетинговая программа
http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/default.aspx
■ Список операторов мобильных сетей, рекомендации по отдельным операторам и контактная информация
http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/smartphoneapps/default.aspx
Развертывание и установкаИнсталляционные технологии постоянно развиваются, и то, какую из них следует использовать, зависит от типа разрабатываемого приложения и вида целевого оборудования. Как и в случае изучения способов взаимодействия с собственными кодами, лучше всего изучать то, что вам необходимо, на конкретных примерах.
Инструкции по развертыванию и установке приложений .NET Compact Framework хорошо изложены в документации продукту MSDN, которая поставляется вместе с Visual Studio .NET. С неплохим примером развертывания приложения на устройствах вы можете ознакомиться в оперативной справочной документации, последовательно выбрав следующие разделы: Visual Studio .NET→Developing with Visual Studio .NET→Designing Distributed Applications→Developing for Devices→Samples and Walkthroughs→Smart Device Walkthroughs→Generating Custom CAB Files for Device Projects (Visual Studio .NET→Разработка с помощью Visual Studio .NET→Проектирование распределенных приложений→Разработка для устройств→Примеры и анализ→Анализ интеллектуальных устройств→Генерация пользовательских CAB-файлов для проектов, ориентированных на устройства).
■ Пошаговый разбор создания инсталляционного приложения для Pocket PC
Developing and Deploying Pocket PC Setup Applications
Автор: Ralph Arvesen; Vertigo Software, Inc.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/netcfdeployment.asp
■ Подробное описание динамической установки .NET Compact Framework на устройствах на тот случай, если это вам когда-либо понадобится
Creating an MSI Package That Detects and Updates the .NET Compact Framework
Автор: Stan Adermann; Microsoft Corporation
http://msdn.microsoft.com/library/default.asp?url=/library/ en-us/dnnetcomp/html/netcfdepl.asp
Профессиональные инструментальные средства разработки инсталляционных программ. В настоящее время некоторые изготовители инсталляционных средств для настольных компьютеров и серверов расширили свои предложения, которые теперь охватывают и мобильные устройства. Вне всякого сомнения, вам стоит ознакомиться с предложениями InstallShield для мобильных устройств,
http://www.installshield.com
Примечание. Я указал здесь InstallShield, учитывая широкую известность и популярность этого средства установки. Если вы используете другие инсталляционные программы, то, безусловно, вам стоит посетить соответствующие Web-сайты, чтобы узнать, поддержку каких мобильных устройств они предлагают.
Оптимизация производительностиВ указанной ниже статье вы найдете превосходные советы и описания эффективных практических методов настройки производительности приложений, а также подробное изложение методик получения данных профилирования приложений с помощью .NET Compact Framework, которые вы сможете применить для анализа производительности приложений. Эта прекрасная статья поможет вам сохранять "дух производительности" в процессе разработки мобильных приложений.
■ Developing Well-Performing .NET Compact Framework Applications
Авторы: Dan Fox, Jon Box; Quilogy
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/netcfperf.asp
ПРИЛОЖЕНИЕ Б
Примеры программ на языке Visual Basic .NET
Почему именно VB.NET и С#?
Споры между разработчиками программ на языках VB.NET и С# никогда не прекращается, и это неплохо! Представителям обоих лагерей есть чему поучиться друг у друга. Что касается меня, то, поработав с обоими языками в течение многих лет, и в частности, имея опыт работы в составе группы разработчиков на Visual Basic, могу поделиться следующими наблюдениями. Каждый из этих языков может быть использован для решения практически любой задачи программирования – все дело в акцентах. Я обнаружил, что Visual Basic .NET с его традиционным для Visual Basic акцентом на продуктивности программирования великолепно приспособлен для разработки конечных приложений.
С другой стороны, преимуществом С# является его строгость, что делает его более приспособленным для проектирования каркасов приложений. По всей видимости, оба языка в равной степени хорошо приспособлены для проектирования повторно используемых компонент, которые занимают промежуточное положение между независимыми приложениями и обширными библиотеками программ. Кроме того, оба языка предлагают опции, отличные от используемых по умолчанию, которые сближают подходы, основанные на использовании каждого из них. Так, в Visual Basic .NET имеется директива Option Strict On, которую я настоятельно рекомендую помещать в начале любого модуля, который вы пишете, в качестве меры, позволяющей вылавливать многие виды распространенных синтаксических и логических ошибок. Помимо этого, оба языка учатся друг у друга, заимствуя каждый с выходом очередной новой версии нечто полезное, что впервые было предложено в другом языке; это порождает хороший дух соперничества между этими двумя языками.
В Visual Basic .NET мне особенно нравятся возможности, относящиеся к обработке событий; ключевые слова AddHandler и Handles (используемые в приведенных ниже кодах) гораздо более элегантны и декларативны, чем их текущие варианты, используемые в С#. Поскольку удобнее всего работать с примерами, которые написаны на наиболее привычном языке, я поместил в данное приложение VB.NET-версии почти всех листингов, приведенных в основной части книги.
Не включены в приложение только листинги примеров, которые, либо в силу малости их размера, либо в силу того, что они должны быть одинаково хорошо понятны разработчикам, принадлежащим любому лагерю, автор счел слишком тривиальными, чтобы тратить время на их трансляцию. Везде, где только возможно, соблюдается практика записи кода, принятая в Visual Basic, в том смысле, что приведенный ниже код является не результатом прямой трансляции кода, написанного на языке C#, а скорее его "VB-версией"; в то же время, оба вида примеров функционально эквивалентны друг другу, и тем, для кого представляет интерес сравнение возможностей языков Visual Basic и C#, чтобы решить для себя, какой из них выбрать, сделать это не составит труда. Удачного программирования!
Примеры к главе 5 (конечные автоматы)
Листинг 5.1. Простой код конечного автомата для игры с множественным выбором
Option Explicit On
Class MyStateMachineClass
Private Enum GameState
StartScreen
AskQuestion
CongratulateUser
ScoldUser
End Enum
Private m_CurrentGameStateAs GameState
'–
'Конечный автомат, воздействующий на пользовательский интерфейс и
'управляющий переходами приложения в другие состояния в соответствии с
'текущим режимом работы пользователя
'––
Private Sub StateChangeForGame(ByVal newGameUIState _
As GameState)
'Определить, в какое состояние переходит приложение
Select Case (newGameUIState)
Case GameState.StartScreen
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If ((m_CurrentGameState <> GameState.CongratulateUser) _
AndAlso (m_CurrentGameState <> GameState.ScoldUser)) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
' SetUpGameStateForStartScreen()
Case GameState.AskQuestion
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If ((m_CurrentGameState <> GameState.StartScreen) _
AndAlso (m_CurrentGameState <> GameState.CongratulateUser) _
AndAlso (m_CurrentGameState <> GameState.ScoldUser)) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
'
' SetUpGameStateForAskQuestion()
Case GameState.CongratulateUser
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
'
' SetUpGameStateForCongratulateUser()
Case GameState.ScoldUser
'Если переход в данное состояние осуществляется из состояния,
'для которого это запрещено, возбудить исключение
If (m_CurrentGameState <> GameState.AskQuestion) Then
Throw New System.Exception("Запрещённое изменение состояния!")
End If
'ЧТО СДЕЛАТЬ: Поместите сюда код, выполняющий следующие операции:
' 1. Скрытие (Hide), отображение (Show) и перемещение (Move)
' элементов управления пользовательского интерфейса
' 2. Настройка переменных/состояний игры, соответствующих
' данному режиму работы
' SetUpGameStateForScoldUser()
Case Else
Throw New System.Exception("Наизвестное состояние!")
End Select
'Сохранить запрошенное новое состояние в качестве текущего
m_CurrentGameState = newGameUIState
End Sub
End Class
Листинг 5.2. Неявное изменение состояния приложения (неудачный подход)
'Код, выполняющийся при загрузке формы
Private Sub Form1_Load(ByVal senderAs System.Object,ByVal _
e As System.EventArgs) Handles MyBase.Load
TextBox1.Visible = True
ListBox1.Visible = False
End Sub
'Данные
Private m_someImportantInfoAs String
'Пользователь щелкнул на кнопке и хочет перейти к выполнению
'следующего шага данного приложения. Скрыть текстовое окно и отобразить
'окно списка в отведенном для этого месте.
Private Sub Button1_Click(ByVal senderAs System.Object,ByVal _
e As System.EventArgs) Handles Button1.Click
m_someImportantInfo = TextBox1.Text
TextBox1.Visible = False
ListBox1.Visible =True
End Sub
Листинг 5.3. Явное изменение состояния приложения (удачный подход)
Private m_someImportantInfo As String
'Определить состояния, в которых может находиться приложение
Enum MyStates
step1
step2
End Enum
'–
'Главная функция, которая
'вызывается всякий раз, когда возникает необходимость
'в изменении состояния приложения
'–
Sub ChangeApplicationState(ByVal newStateAs MyStates)
Select Case newState
Case MyStates.step1
TextBox1.Visible = True
ListBox1.Visible = False
Case MyStates.step2
m_someImportantInfo = TextBox1.Text
TextBox1.Visible = False
ListBox1.Visible = True
End Select
End Sub
'–
'Пользователь щелкнул на кнопке и хочет перейти к выполнению
'следующего шага данного приложения. Скрыть текстовое окно и отобразить
'окно списка в отведенном для этого месте.
'–
Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
'Вызвать главную функцию для изменения состояния
ChangeApplicationState(MyStates.step2)
End Sub
'–
'Код, выполняющийся при загрузке формы
'–
Private Sub Forml_Load(ByVal sender As Object, _
ByVal eAs System.EventArgs)
'Вызвать главную функцию для изменения состояния
ChangeApplicationState(MyStates.step1)
End Sub
Листинг 5.4. Код программы нахождения простых чисел, предназначенный для выполнения фоновым потоком
Option Strict On
Imports System
Public Class FindNextPrimeNumber
'Определить возможные состояния
Public Enum ProcessingState
notYetStarted
waitingToStartAsync
lookingForPrime
foundPrime
requestAbort
aborted
End Enum
Private m_startTickCount As Integer
Private m_endTickCount As Integer
Private m_startPoint As Long
Private m_NextHighestPrime As Long
Private m_processingState As ProcessingState
'–
'Простейший конечный автомат
'–
Public Sub setProcessingState(ByVal nextState As ProcessingState)
'–
'Простейший защитный код, гарантирующий
'невозможность перехода в другое состояние в случае успешного
'завершения задачи или успешной отмены ее выполнения
'–
Dim currentState As ProcessingState
currentState = getProcessingState()
If ((currentState = ProcessingState.aborted) _
OrElse (currentState = ProcessingState.foundPrime)) Then
Return
End If
'Безопасное параллельное выполнение потоков
SyncLock (Me)
'Разрешить изменение состояния
m_processingState = nextState
End SyncLock
End Sub
Public Function getProcessingState() As ProcessingState
Dim currentState As ProcessingState
'Безопасное параллельное выполнение потоков
SyncLock (Me)
currentState = m_processingState
End SyncLock
Return currentState
End Function
Public Function getTickCountDelta() As Integer
If (getProcessingState() = _
ProcessingState.lookingForPrime) Then
Throw New Exception( _
"Продолжается поиск простого числа! Окончательное время еще не вычислено")
End If
Return m_endTickCount – m_startTickCount
End Function
'–
'Возвращает простое число
'–
Public Function getPrime() As Long
If (getProcessingState() <> ProcessingState.foundPrime) Then
Throw New Exception("Простое число еще не найдено!")
End If
Return m_NextHighestPrime
End Function
'Конструктор класса
Public Sub New(ByVal startPoint As Long)
setProcessingState(ProcessingState.notYetStarted)
m_startPoint = startPoint
End Sub
'–
'Создает новый рабочий поток, который будет вызывать функцию
'findNextHighestPrime()
'–
Public Sub findNextHighestPrime_Async()
Dim threadStartAs System.Threading.ThreadStart
threadStart = _
New System.Threading.ThreadStart( _
AddressOf findNextHighestPrime)
Dim newThread As System.Threading.Thread
newThread = New System.Threading.Thread(threadStart)
'Состояние должно отвечать, что поиск продолжается
setProcessingState(ProcessingState.waitingToStartAsync)
newThread.Start()
End Sub
'–
'Основной рабочий поток. Этот поток запускает поиск очередного
'простого числа и выполняется до тех пор, пока не произойдет
'одно из следующих двух событий:
' (а) найдено очередное простое число
' (b) от внешнего (по отношению к данному) потока поступила команда
' прекратить выполнение
'–
Public Sub findNextHighestPrime()
'Если поступила команда прекратить выполнение, то поиск даже
'не должен начинаться
If (getProcessingState() = ProcessingState.requestAbort) Then
GoTo finished_looking
End If
'Состояние должно отвечать, что поиск продолжается
setProcessingState(ProcessingState.lookingForPrime)
m_startTickCount = System.Environment.TickCount
Dim currentItemAs Long
'Проверить, является ли число нечетным
If ((m_startPointAnd 1) = 1) Then
'Число является нечетным, начать поиск со следующего нечетного числа
currentItem = m_startPoint + 2
Else
'Число является четным, начать поиск со следующего нечетного числа
currentItem = m_startPoint + 1
End If
'Приступить к поиску простого числа
While (getProcessingState() = ProcessingState.lookingForPrime)
'В случае нахождения простого числа возвратить его
If (isItemPrime(currentItem) = True) Then
m_NextHighestPrime = currentItem
'Обновить состояние
setProcessingState(ProcessingState.foundPrime)
End If
currentItem = currentItem + 2
End While
finished_looking:
'Выход. К этому моменту либо от другого потока поступила
'команда прекратить поиск, либо было найдено и записано
'следующее наибольшее простое число
'Зафиксировать время
m_endTickCount = System.Environment.TickCount
'Если поступил запрос прекратить выполнение,
'сообщить, что выполнение процесса прекращено
If (getProcessingState() = ProcessingState.requestAbort) Then
setProcessingState(ProcessingState.aborted)
End If
End Sub
'Вспомогательная функция, которая проверяет, является
'ли число простым
Private Function isItemPrime(ByVal potentialPrime As Long) As Boolean
'Если число – четное, значит, оно не является простым
If ((potentialPrime And 1) = 0) Then
Return False
End If
'Продолжать поиск до тех пор, пока не будет превышено значение
'квадратного корня из числа
Dim end_point_of_searchAs Long end_point_of_search = _
CLng(System.Math.Sqrt(potentialPrime) + 1)
Dim current_test_itemAs Long = 3
While (current_test_item <= end_point_of search)
'–
'Проверить, не поступила ли команда прекратить выполнение!
'–
If (getProcessingState() <> ProcessingState.lookingForPrime) Then
Return False
End If
'Если число делится без остатка,
'значит, оно не является простым
If (potentialPrimeMod current_test_item = 0) Then
Return False
End If
'Увеличить число на два
current_test_item = current test_item + 2
End While
'Число является простым
Return True
End Function
End Class
Листинг 5.5. Тестовая программа, которая вызывает на выполнение приведенный выше код фонового потока, осуществляющего поиск простого числа
'–
'Код, обрабатывающий событие щелчка на кнопке Button1 формы
'Вызвать из этого потока функцию поиска простого числа!
'(Это приведет к блокированию потока)
'–
Private Sub Button1_Click(ByVal senderAs System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim testItem As Long
testItem = System.Convert.ToInt64("123456789012345")
Dim nextPrimeFinder As FindNextPrimeNumber
nextPrimeFinder = New FindNextPrimeNumber(testItem)
nextPrimeFinder.findNextHighestPrime()
Dim nextHighestPrime As Long
nextHighestPrime = nextPrimeFinder.getPrime()
MsgBox(CStr(nextHighestPrime))
'Сколько времени заняли вычисления?
Dim calculation_time As Integer
calculationtime = nextPrimeFinder.getTickCountDelta()
MsgBox(CStr(calculation time) + " мс")
End Sub
'–
'Код, обрабатывающий событие щелчка на кнопке Button2 формы
'Вызвать функцию поиска простого числа из другого потока!
'(Данный поток блокироваться не будет)
'Для отслеживания состояния выполнения задачи используем конечный автомат
'–
Private Sub Button2_Click(ByVal senderAs System.Object, _
ByVal eAs System.EventArgs) Handles Button2.Click
Dim testItem As Long
testItem = System.Convert.ToInt64("123456789012345")
Dim nextPrimeFinderAs FindNextPrimeNumber
nextPrimeFinder = New FindNextPrimeNumber(testItem)
'–
'Выполнить обработку в другом потоке
'–
nextPrimeFinder.findNextHighestPrime_Async()
'Войти в цикл и ожидать до тех пор, пока не будет найдено простое число
'или выполнение не будет прекращено
While ((nextPrimeFinder.getProcessingState() <> _
FindNextPrimeNumber.ProcessingState.foundPrime) And _
(nextPrimeFinder.getProcessingState() <> _
FindNextPrimeNumber.ProcessingState.aborted))
'ТОЛЬКО В ТЕСТОВОМ КОДЕ:
'Отобразить окно сообщений и предоставить пользователю возможность
'убрать его с экрана.
'Это позволяет организовать паузу
MsgBox("Поиск продолжается... Щелкните на кнопке OK")
'Мы могли бы прекратить поиск путем следующего вызова функции:
'nextPrimeFinder.setProcessingState(
' FindNextPrimeNumber.ProcessingState.requestAbort)
End While
'Осуществить корректный выход в случае прекращения поиска
If (nextPrimeFinder.getProcessingState() = _
FindNextPrimeNumber.ProcessingState.aborted) Then
MsgBox("Поиск прекращен!")
Return
End If
Dim nextHighestPrime As Long
nextHighestPrime = nextPrimeFinder.getPrime()
MsgBox(CStr(nextHighestPrime))
'Сколько времени заняли вычисления?
Dim calculation_time As Integer
calculation_time = nextPrimeFinder.getTickCountDelta()
MsgBox(CStr(calculation_time) + " мс")
End Sub







