Кратко съдържание


Хостинг на контроли в Internet Explorer



страница23/33
Дата23.07.2016
Размер10.53 Mb.
#1889
1   ...   19   20   21   22   23   24   25   26   ...   33

Хостинг на контроли в Internet Explorer


Internet Explorer може да изпълнява Windows Froms контроли, вградени в тялото на HTML страници. Технологията е подобна на Java аплетите и Macromedia Flash – вгражда се изпълним код, който се изпълнява в клиентския уеб браузър. От JavaScript могат да се достъпват свойствата на Windows Forms контролите. Необходими са Internet Explorer 5.5, или по-нова версия, и инсталиран .NET Framework.

Настройките за сигурност не позволяват достъп до файловата система и други опасни действия. Сигурността може да се задава и ръчно. Ако има нужда от запазване на някакви данни на машината на потребителя, може да се използва Isolated Storage.


Хостинг на контроли в Internet Explorer – пример


Настоящият пример илюстрира как можем да реализираме хостинг на Windows Forms контроли в Internet Explorer чрез вграждането им в HTML страница и как можем да достъпваме свойствата им от JavaScript.

Да разгледаме примерна HTML страница, в която е вградена Windows Forms контролата "часовник" от предходния пример:



index.html





Clock Control in IE
classid="http:Demo-18-CustomControl-Clock.exe#Demo_18_CustomControl_Clock.ClockControl"

width="200" height="200">

Hour:


Minute:





Как работи примерът?


Нека разгледаме по-подробно отделните части на HTML страницата. Чрез HTML тага вмъкваме в страницата нашата контрола. Това е часовникът, който създадохме в предишния пример. Атрибутът id, който има стойност clockContol, указва идентификатор, чрез който ще можем да достъпваме обекта в HTML страницата, а атрибу­ти­те width и height указват с каква ширина и височина да се изобрази той. Атрибутът classid определя класа на вмъквания обект. В случая това е нашата ClockControl контрола. Забележете, че указваме асемблито, пространството и името на класа в стойността на този атрибут. В случая сме поставили асемблито Demo-18-CustomControl-Clock.exe в директорията, в която се намира и HTML страницата. Чрез таговете
задаваме стойности за свой­ства­та на изобразяваната контрола.

Под контролата сме поставили две текстови полета и един бутон. Тексто­ви­те полета служат за въвеждане на час и минути, които да показва ча­сов­никът. Бутонът служи за промяна на стрелките на часовника. При на­тис­кането му се извиква JavaScript функцията ChangeText(), дефи­ни­ра­на в началото на страницата, която променя свойствата на контролата. Достъпът до текстовите полета и до контролата се извършва посредством техните идентификатори, зададени чрез атрибута id.


Примерът в действие


За да видим резултата от нашата работа, трябва да използваме Internet Explorer 5.5 или по-нов. Не е известен друг уеб браузър, който поддържа Windows Forms контроли.

Ако отворим директно index.html в Internet Explorer, контролата ClockControl няма да се зареди заради политиката за сигурност, която не позволява локално разположени HTML документи да изпълняват Windows Forms контроли. Необходимо е страницата да бъде публикувана на няка­къв уеб сървър, например IIS.

Нека файловете ни се намират в папката Demo-19-Custom-Controls-in-IE. Публикуването на папката в Internet Information Services (IIS) се извършва по следния начин:


  1. От свойствата на папката Demo-19-Custom-Controls-in-IE, дос­тъп­ни от диалоговата кутия на Windows Explorer, избираме таба "Web Sharing". В него избираме "Share this folder".



  1. Публикуваме папката Internet Information Services, като позволим четене на файловете и листинг на директориите.

Сега можем да отворим с Internet Explorer URL адреса на примера от публикуваната в IIS директория:



http://localhost/Demo-19-Custom-Controls-in-IE/index.html

Ще получим следния резултат:



Ако въведем час и минута и натиснем бутона, стрелките ще променят местоположението си.


Нишки и Windows Forms


Продължителните операции в Windows Forms приложенията трябва да се изпълняват в отделна нишка. В противен случай се получава "заспиване" на потребителския интерфейс. Как можем да използваме нишки, ще разгледаме подробно в темата "Многонишково програмиране и синхрони­зация", но засега можем да считаме, че нишките позволяват паралелно изпълне­ние на програмен код в нашите приложения.

Да вземем за пример операцията "изтегля­не на файл от Интернет". Тя може да отнеме от няколко секунди до някол­ко часа и е недопустимо приложението да блокира, докато изтеглянето на файла не приключи. В такъв случай трябва да изпълним задачата в друга нишка (thread) и от време на време да показваме на потребителя индикация за напредъка, например чрез контролата ProgressBar. Има обаче един проблем, свър­зан с достъпа до потребителския интерфейс при работа с нишки.

Обновяването на потребителския интерфейс на дадена контрола трябва да става само от ниш­ка­та, в която работи контролата. От друга нишка безопасно могат да се извикват са­мо методите Invoke(), BeginInvoke(), EndInvoke() и CreateGraphics().



Никога не обновявайте Windows Forms контроли от нишка, която не ги притежава!

За изпълнение на методи от нишката, която притежава дадена контро­ла, изпол­зва­ме метода Invoke(…) на класа Control. Ето пример:

delegate void StringParamDelegate(string aValue);
class Form1 : System.Windows.Forms.Form

{

private void UpdateUI(string aValue)



{

// Update UI here …

// This code is called from the Form1's thread

}
void AsynchronousOperation()

{

// This runs in separate thread. Invoke UI update



this.Invoke(new StringParamDelegate(UpdateUI),

new object[]{"някакъв параметър"});

}

}


По този начин нишката, която извършва времеотнемащата работа, работи паралелно на нишката, която управлява потребителския интерфейс, но той се обновява само от неговата нишка-собственик. Ако обновяваме потребителския интерфейс от нишката, която извършва времеотнемащата операция, а не от главната нишка на приложението, се получават много странни ефекти – от "зависване" на приложението до неочаквани изключения и системни греш­ки. Не го правете!

Използване на нишки в Windows Forms приложения – пример


С настоящия пример ще илюстрираме използването на нишки (threads) в Windows Forms приложения за изпълнение на времеотнемащи задачи. Ще покажем правилния начин, по който една нишка, която се изпълнява паралелно с главната нишка на Windows Forms приложението, може да обновява неговия потребителски интер­фейс.

Приложението, което ще създадем, ще търси прости числа (което е време­отнемаща операция) и ще ги показва на потребителя. Търсенето ще се извършва в отделна, паралелно изпълняваща се нишка, за да не "заспива" потребителският интерфейс.

Ето стъпките за изграждане на нашето приложение:


  1. Стартираме VS.NET и създаваме нов Windows Forms проект.

  2. Задаваме на главната форма име MainForm и заглавие "Asynchronos UI Update Demo". Променяме и името на файла от Form1.cs на MainForm.cs.

  3. Добавяме във формата два бутона с имена ButtonStart и ButtonStop и един TextBox с име TextBoxLastPrimeNumber. На свойствата Text на бутоните задаваме съответно стойности Start и Stop. Задаваме стойност false на свойството Enabled на бутона ButtonStop.

  4. Добавяме променлива за нишката, която търси прости числа:

    private Thread mPrimeNumbersFinderThread = null;

  5. Декларираме делегат, който ще използваме при извикването на метода Invoke(…), когато обновяваме потребителския интерфейс:

    delegate void LongParameterDelegate(long aValue);

  6. Дефинираме клас PrimeNumberFinder, чрез който ще търсим прости числа в интервала [0; 1 000 000 000]:

class PrimeNumbersFinder

{

private MainForm mMainForm;


public PrimeNumbersFinder(MainForm aMainForm)

{

mMainForm = aMainForm;



}
public void FindPrimeNumbers()

{

for (long number=0; number<1000000000; number++)



{

if (IsPrime(number))

{

mMainForm.Invoke(



new LongParameterDelegate(mMainForm.ShowPrimeNumber),

new object[]{number}

);

}

}



}
private bool IsPrime(long aNumber)

{

// Primarity testing. Very ineffective.



// Don't do it in a real case!!!

for (long i=2; i

{

// Just waste some CPU time



int sum = 0;

for (int w=0; w<100000; w++)

{

sum += w;



}
if (aNumber % i == 0)

{

return false;



}

}
return true;

}

}


Понеже търсенето на прости числа ще се извършва в отделна нишка, в класа сме дефинирали променлива mMainForm, чрез която ще се обръщаме към главната форма, за да обновяваме потребителския интерфейс. Тази променлива се инициализира в конструктора на класа.

Методът IsPrime(…) проверява дали подаденото като параметър число е просто. Тази проверка нарочно се прави по изключително времеотнемащ, неефек­ти­вен и натоварващ процесора начин, за да се симулира забавяне.

Методът FindPrimeNumbers() проверява последователно дали е просто вся­ко от числата в интервала от 0 до 1000000000. Ако числото е просто, през главната нишка на приложението се извиква методът ShowPrimeNumber(…), като му се подава като параметър намереното прос­то число. Този метод показва числото в потребителския интерфейс. Извикването се извършва чрез метода Invoke(…) на формата, който има гри­жата да изпълни подадения му делегат през нишката, в която работи фор­мата.

Нишката, която търси прости числа, няма право да променя директно потребителския интерфейс на приложението, защото той работи в друга нишка. Ако две нишки работят с потребителския интерфейс едновремен­но, могат да възникнат непредвидими проблеми – блокиране на приложе­ние­то, странни изключения или странни визуални ефекти.



  1. Дефинираме в главната форма метода ShowPrimeNumber(…), който показва подаденото му като параметър число в текстовото поле TextBoxLastPrimeNumber:

    internal void ShowPrimeNumber(long aNumber)

    {

    TextBoxLastPrimeNumber.Text = aNumber.ToString();



    }

  2. Добавяме обработчик на събитието Click на бутона ButtonStart. В него деактивираме Start бутона, активираме бутона Stop и стар­ти­ра­ме отделна нишка, в която започваме да търсим прости числа:

    private void ButtonStart_Click(object sender,System.EventArgs e)

    {

    ButtonStart.Enabled = false;



    ButtonStop.Enabled = true;

    PrimeNumbersFinder finder = new PrimeNumbersFinder(this);

    mPrimeNumbersFinderThread =

    new Thread(new ThreadStart(finder.FindPrimeNumbers));

    mPrimeNumbersFinderThread.Start();

    }


  3. Добавяме обработчик на събитието Click на бутона ButtonStop. В него активираме Start бутона, деактивираме бутона Stop и пре­кра­­тяваме изпълнението на стартираната нишка:

    private void ButtonStop_Click(object sender, System.EventArgs e)

    {

    ButtonStart.Enabled = true;



    ButtonStop.Enabled = false;

    mPrimeNumbersFinderThread.Abort();

    }


  4. Добавяме обработчик на събитието Closing на главната форма. В него прекратяваме изпълнението на нишката, търсеща прости чис­ла (в случай че е била стартирана):

    private void MainForm_Closing(object sender,

    System.ComponentModel.CancelEventArgs e)

    {

    if (mPrimeNumbersFinderThread != null)



    {

    mPrimeNumbersFinderThread.Abort();

    }

    }


  5. Приложението е готово и можем да го стартираме и тестваме.

Въпреки че се извършва тежко изчисление и процесорът е натоварен на 100%, потребителският интерфейс не "замръзва". Ако все пак в даден момент се получи замръзване за кратко време, най-вероятно причината за това e включването на системата за почистване на паметта (Garbage Collector).





Сподели с приятели:
1   ...   19   20   21   22   23   24   25   26   ...   33




©obuch.info 2024
отнасят до администрацията

    Начална страница