PODSTAWY PROGRAMOWANIA

Podobne dokumenty
Zaawansowane programowanie w (pakiecie) Delphi

Zaawansowane programowanie w (pakiecie) Delphi

Wprowadzenie do systemu Delphi

Tworzenie własnych komponentów

Język programowania DELPHI / Andrzej Marciniak. Poznań, Spis treści

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Nazwa implementacji: Kółko i krzyżyk w Lazarusie. Autor: Piotr Fiorek Andrzej Stefaniuk

Wstęp do programowania. Procedury i funkcje. Piotr Chrząstowski-Wachtel

Podstawy Programowania 2

Obsługa grafiki w Delphi, rysowanie na płótnie, obsługa myszki, zapisywanie obrazków do plików, bitmapy pozaekranowe.

Materiały do laboratorium MS ACCESS BASIC

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

Kierunek: ETI Przedmiot: Programowanie w środowisku RAD - Delphi Rok III Semestr 5. Ćwiczenie 5 Aplikacja wielo-okienkowa

Wstęp do programowania. Różne różności

Rozdział 4 KLASY, OBIEKTY, METODY

Delphi Laboratorium 3

PODSTAWY PROGRAMOWANIA

Wstęp do programowania 2

Podstawy programowania. Wykład PASCAL. Zmienne wskaźnikowe i dynamiczne. dr Artur Bartoszewski - Podstawy prograowania, sem.

WYKONANIE APLIKACJI OKIENKOWEJ OBLICZAJĄCEJ SUMĘ DWÓCH LICZB W ŚRODOWISKU PROGRAMISTYCZNYM. NetBeans. Wykonał: Jacek Ventzke informatyka sem.

Programowanie w Turbo Pascal

Opis implementacji: Implementacja przedstawia Grę w życie jako przykład prostej symulacji opartej na automatach.

5. Model komunikujących się procesów, komunikaty

PROGRAM: WYSZUKANIE LICZBY MAKSYMALNEJ

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

TEMAT : KLASY DZIEDZICZENIE

procesów Współbieżność i synchronizacja procesów Wykład prowadzą: Jerzy Brzeziński Dariusz Wawrzyniak

Wątek - definicja. Wykorzystanie kilku rdzeni procesora jednocześnie Zrównoleglenie obliczeń Jednoczesna obsługa ekranu i procesu obliczeniowego

Mechanizmy pracy równoległej. Jarosław Kuchta

Tworzenie aplikacji Windows Podstawy obsługi komunikatów Windows (Delphi)

Język programowania. Andrzej Bobyk

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Programowanie na poziomie sprzętu. Programowanie w Windows API

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Podstawy Programowania semestr drugi. Wykład czternasty

Wykład 5 Okna MDI i SDI, dziedziczenie

Procedury i funkcje - powtórzenie i uzupełnienia. Przykład funkcji potęgowanie przy wykładniku naturalnym

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Pascal - wprowadzenie

Delphi 7 + Indy 10 Przykłady prostych aplikacji sieciowych

Wykład 8: klasy cz. 4

Pascal typy danych. Typy pascalowe. Zmienna i typ. Podział typów danych:

Delphi podstawy programowania. Środowisko Delphi

Budowa aplikacji z graficznym interfejsem użytkownika - GUI (Graphic User Interface)

Dodawanie operacji dodatkowych w WAPRO Mag.

Programowanie obiektowe

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Lekcja 5. Funkcje handlemessage() i initialize(), konstruktor i destruktor

3 Delegacje. 3.1 Tworzenie delegacji. 3.2 Skojarzenie delegacji z procedurą czy funkcją

16) Wprowadzenie do raportowania Rave

Podstawy Programowania C++

Politechnika Poznańska Wydział Budowy Maszyn i Zarządzania

Tak przygotowane pliki należy umieścić w głównym folderze naszego programu. Klub IKS

PODSTAWY PROGRAMOWANIA

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Język programowania PASCAL

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Smarty PHP. Leksykon kieszonkowy

Instrukcja do programu Do7ki 1.0

Zapis programu z wykorzystaniem modułu (Podstawy Delphi 2.1, 2.2, 2.3 str11 )

Programowanie RAD Delphi

Laboratorium 15: Bazy Danych Tworzenie bazy danych i programowanie elementów nawigacyjnych aplikacji stworzonej przy pomocy technologii dbexpress

Multimedia JAVA. Historia

PODSTAWY PROGRAMOWANIA

Programowanie w Sieci Internet Blok 2 - PHP. Kraków, 09 listopada 2012 mgr Piotr Rytko Wydział Matematyki i Informatyki

Programowanie w języku Python. Grażyna Koba

Programowanie równoległe i rozproszone. Monitory i zmienne warunku. Krzysztof Banaś Programowanie równoległe i rozproszone 1

Programowanie obiektowe

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

Kalkulator. Programowanie komputerów. Kalkulator możliwe udoskonalenia. Kalkulator. Kalkulator. Kalkulator możliwe udoskonalenia

Przykładowa dostępna aplikacja w Visual Studio - krok po kroku

BAZY DANYCH Panel sterujący

Baltie 3. Podręcznik do nauki programowania dla klas I III gimnazjum. Tadeusz Sołtys, Bohumír Soukup

Laboratorium Systemów SCADA

Klasy abstrakcyjne i interfejsy

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Współbieżność w środowisku Java

Ćwiczenie: JavaScript Cookies (3x45 minut)

PARADYGMATY PROGRAMOWANIA Wykład 4

Programowanie obiektowe

Programowanie obiektowe

Zaawansowane programowanie w (pakiecie) Delphi

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

15. Funkcje i procedury składowane PL/SQL

OPERACJE NA PLIKACH. Podstawowe pojęcia:

Instrukcja do programu DoUPS 1.0

PHP: bloki kodu, tablice, obiekty i formularze

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Aplikacje w środowisku VBA. Visual Basic for Aplications

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Programowanie obiektowe

Informatyka 1. Przetwarzanie tekstów

Microsoft Visual C++

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Projektowanie i programowanie aplikacji biznesowych. Wykład 2

Programowanie wielowątkowe. Jarosław Kuchta

Transkrypt:

PODSTAWY PROGRAMOWANIA Andrzej Marciniak Prezentacja multimedialna przygotowana za pomocą systemu Corel Presentations X3 Copyright 2004-2018 by Andrzej Marciniak PP-14(1 z 76)

Na poprzednim wykładzie... system pomocy dla programu okienkowego wyświetlanie wskazówek dołączanie plików pomocy i ich obsługa w języku Delphi przygotowanie wersji dystrybucyjnej programu program InstallShield Express plik AUTORUN.INF tworzenie komponentów VCL i ActiveX oraz ich wykorzystanie konstrukcja komponentu VCL testowanie komponentu VCL konstrukcja komponentu ActiveX PP-14(2 z 76)

Na tym wykładzie... wielozadaniowość w środowisku Windows programowanie sterowane zdarzeniami wysyłanie wiadomości do okienek (funkcje PostMessage i SendMessage) sprawdzanie obecności poprzedniego egzemplarza programu wielowątkowość pojęcie procesu i wątku zmienne wątkowe klasa TThread priorytety wątków synchronizacja wątków PP-14(3 z 76)

Wielozadaniowość... Programowanie sterowane zdarzeniami Środowisko Windows w wersji 32- i 64-bitowej pozwala na jednoczesne uruchamianie wielu programów oraz aktywację wielu wątków dla jednego programu. Podstawowa koncepcja programowania sterowanego zdarzeniami polega na tym, że przebieg programu determinują zdarzenia. Program spędza większość czasu oczekując na te zdarzenia i posiada kod na nie reagujący. Zdarzenia są uszeregowane każde zdarzenie jest obsługiwane dopiero po zakończeniu obsługi poprzedniego. Zdarzenia są w środowisku Windows identyfikowane przez wiadomości. PP-14(4 z 76)

Wielozadaniowość... Programowanie sterowane zdarzeniami W 16-bitowym środowisku Windows 3.1 nie było możliwości przerwania procedury obsługi wiadomości. W obecnych wersjach środowiska Windows po upływie ustalonego czasu system przekazuje wiadomość do obsługi do kolejnej aplikacji na liście. Dopiero, gdy skończą działanie wszystkie aplikacje, wznawiana jest pierwsza z nich. Nazywa się to wielozadaniowością z wywłaszczaniem. Po obsłużeniu wiadomości program staje się nieaktywny do chwili otrzymania innej wiadomości (chyba że stosuje się wielowątkowość będzie dalej). PP-14(5 z 76)

Wielozadaniowość... Programowanie sterowane zdarzeniami Dla programu uruchomionego w środowisku Windows zdarzenia wejściowe (spowodowane przez myszkę lub klawiaturę) generują jedynie niewielką część całkowitego przepływu wiadomości większość komunikatów to wewnętrzne wiadomości środowiska Windows i wiadomości wymieniane pomiędzy różnymi elementami sterującymi i oknami. PP-14(6 z 76)

Wielozadaniowość... Wysyłanie wiadomości do okien W środowisku Windows są dwa różne sposoby wysyłania wiadomości do okien: za pomocą funkcji API PostMessage służy do umieszczenia wiadomości w kolejce wiadomości programu; wiadomość zostanie obsłużona tylko wówczas, gdy dany program przejmie sterowanie od systemu i tylko po obsłużeniu wcześniejszych wiadomości (jest to wywołanie asynchroniczne, gdyż nie wiadomo, kiedy wiadomość będzie rzeczywiście odebrana), PP-14(7 z 76)

Wielozadaniowość... Wysyłanie wiadomości do okien W środowisku Windows są dwa różne sposoby wysyłania wiadomości do okien: za pomocą funkcji API SendMessage służy do natychmiastowego wykonania kodu procedury obsługi wiadomości; funkcja ta omija kolejkę wiadomości programu i wysyła wiadomość bezpośrednio do docelowego okna lub elementu sterującego (jest to wywołanie synchroniczne). Różnica pomiędzy tymi sposobami wysyłania wiadomości przypomina różnicę pomiędzy wysłaniem pocztą listu, który dotrze do miejsca przeznaczenia wcześniej lub później, a wysłaniem faksu, który dociera natychmiast do odbiorcy ṖP-14(8 z 76)

Wielozadaniowość... Wysyłanie wiadomości do okien Wywołanie funkcji PostMessage ma postać PostMessage (identyfikator, wiadomość, WParam, LParam) gdzie: identyfikator (typu HWND identycznego z typami THandle i LongWord) identyfikator okna nadawany przez środowisko Windows (można go otrzymać za pomocą funkcji FindWindow będzie dalej), wiadomość (typu UINT identycznego z typem LongWord) określa przesyłaną wiadomość (najczęściej za pomocą stałej o przedrostku wm_), WParam i LParam (typów odpowiednio WPARAM i LPARAM identycznych z typem LongInt) określają dodatkowe informacje związane z daną wiadomością. PP-14(9 z 76)

Wielozadaniowość... Wysyłanie wiadomości do okien Funkcję SendMessage wywołuje się z takimi samymi parametrami: SendMessage (identyfikator, wiadomość, WParam, LParam) Przypomnienie: Wiadomości środowiska Windows są identyfikowane za pomocą stałych, a przesyłane w rekordach o ogólnym, predefiniowanym typie TMessage (jest on zdefiniowany w module Vinapi.Messages). PP-14(10 z 76)

Wielozadaniowość... Obsługa wiadomości (przypomnienie) Metoda służąca do obsługi wiadomości powinna być zadeklarowana w sekcji private definicji typu klasowego i musi być metodą-procedurą. Deklaracja takiej metody zawiera dyrektywę języka message, po której występuje stała całkowita określająca wiadomość (na ogół stałą tę określa się za pomocą identyfikatora, którego nazwa kojarzy się z obsługiwaną wiadomością). Metody obsługujące wiadomości nie mogą być pokrywane przy użyciu dyrektywy języka override. Ewentualne pokrycie takiej metody w typie potomnym jest jednoznacznie określone przez stałą podaną po dyrektywie message. PP-14(11 z 76)

Wielozadaniowość... Obsługa wiadomości (przypomnienie) Oprócz funkcji PostMessage i SendMessage do wywołania metody obsługi wiadomości można także zastosować metodę-procedurę Dispatch (zdefiniowaną w typie TObject). Wywołanie metody Dispatch ma postać Dispatch (wiadomość) gdzie wiadomość oznacza rekord (dokładniej: zmienną nieokreślonego typu), którego pierwsze pole (cztery bajty) powinno być typu Cardinal. Wartość tego pola identyfikuje wysyłaną wiadomość. Pozostałe pola rekordu mogą zawierać informacje specyficzne dla przetwarzanej wiadomości. PP-14(12 z 76)

Wielozadaniowość... Obsługa wiadomości (przypomnienie) Wywołanie metody Dispatch powoduje wywołanie najbliższej metody obsługującej daną wiadomość. Metoda ta jest poszukiwana najpierw w klasie, w której nastąpiło wywołanie metody Dispatch, następnie w klasie bezpośrednio nadrzędnej, po czym w kolejnej klasie poprzedniej (przodku) itd., aż do osiągnięcia klasy TObject. Jeśli po drodze nie napotkano właściwej metody, to nastąpi wywołanie standardowej metody obsługi DefaultHandler zdefiniowanej w klasie TObject. PP-14(13 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Każdy program może być wykonany w więcej niż jednym egzemplarzu. Aby zezwolić na co najwyżej jeden egzemplarz, program musi mieć możliwość sprawdzenia, czy poprzedni egzemplarz nie jest już uruchomiony. Poznamy trzy sposoby rozwiązania tego problemu: zastosowanie funkcji API FindWindow, użycie muteksu, przeszukanie listy okien. PP-14(14 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Zastosowanie funkcji FindWindow Wartością funkcji FindWindow (z modułu Winapi.Windows) jest identyfikator okna (ang. handle) nadawany przez środowisko Windows lub 0, jeśli okno nie zostanie znalezione. Identyfikator ten jest typu HWND: type HWND = type LongWord; Typ ten jest zgodny m. in. z typem THandle (który zaleca się stosować). PP-14(15 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Zastosowanie funkcji FindWindow Wywołanie funkcji ma postać FindWindow (nazwa-klasy, nazwa-okna) Oba parametry są typu PChar. Wartość nil drugiego parametru oznacza, że nazwa okna może być dowolna. Główny kod (kod programu) powinien być napisany tak, by był wykonywany tylko wówczas, gdy wartością funkcji FindWindow jest 0: PP-14(16 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Zastosowanie funkcji FindWindow... var ident : THandle; begin ident:=findwindow( TForm1, nil); if ident=0 end. wykonanie, gdy okna nie odnaleziono then begin Application.Initialize; Application.CreateForm(TForm1, Form1);... Application.Run end else SetForegroundWindow (ident) uaktywnienie poprzedniego egzemplarza programu PP-14(17 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Zastosowanie funkcji FindWindow Technika ta działa tylko wówczas, gdy główne okno poprzedniego egzemplarza programu nie zostało zminimalizowane. Gdy główne okno jest zminimalizowane, to jest ukryte i kod aktywujący nie działa. Program nie uruchomi się także w przypadku, gdy uruchomiono inny program, którego aktualnie aktywne (może jedyne) okno ma taką samą nazwę (Form1 w rozważanym przykładzie). PP-14(18 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu muteks obiekt wzajemnie wykluczający się (w środowisku Windows może istnieć tylko jeden muteks o danej nazwie) Po utworzeniu przez program obiektu muteksu o danej nazwie lub sprawdzeniu, że taki obiekt już istnieje (za pomocą funkcji CreateMutex), program może sprawdzić, czy obiekt ten jest już w posiadaniu innego programu. W tym celu wywołuje się funkcję WaitForSingleObject. PP-14(19 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu Wywołanie funkcji CreateMutex ma postać CreateMutex (atrybuty-bezpieczeństwa, czy-właściciel, nazwa-muteksu) Pierwszy parametr określa, czy identyfikator muteksu może być dziedziczony przez procesy potomne (jeśli jest on równy nil, to identyfikator ten nie może być dziedziczony taką wartość należy przyjąć w rozważanym problemie). PP-14(20 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu Wywołanie funkcji CreateMutex ma postać CreateMutex (atrybuty-bezpieczeństwa, czy-właściciel, nazwa-muteksu) Wartość True dugiego parametru oznacza, że program (proces) wywołujący funkcję staje się właścicielem muteksu (w naszym problemie parametr ten powinien mieć wartość False). Trzeci parametr (typu PChar) określa nazwę muteksu. Wartość funkcji (typu THandle) jest identyfikatorem muteksu (nadawanym przez środowisko Windows). PP-14(21 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu Działanie funkcji WaitForSingleObject* ) jest następujące: jeśli muteks nie ma właściciela, funkcja powoduje, że jego właścicielem staje się program wywołujący (tę funkcję). Jeśli muteks ma już właściciela, program czeka aż upłynie czas podany w wywołaniu funkcji, a następnie funkcja przekazuje (jako wartość) kod błędu. * ) w stosunku do muteksu, bo w ogólności funkcja może działać na różnych obiektach PP-14(22 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu Wywołanie funkcji WaitForSingleObject : WaitForSingleObject (identyfikator-obiektu, czas-oczekiwania) Jeśli wartością drugiego parametru jest 0, funkcja testuje stan podanego obiektu i natychmiast podaje wynik (co jest pożądane w rozważanym problemie). Wartość funkcji określa zdarzenie, które spowodowało zakończenie testowania. Do zbadania tej wartości wykorzystuje się stałe o przedrostku wait_ (zob. system pomocy). W naszym problemie należy zbadać, czy wartość funkcji jest różna od wait_timeout (w przypadku muteksu stała ta oznacza, że ma on już właściciela). PP-14(23 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu... var muteks : THandle; begin Użycie muteksu utworzenie muteksu i (lub) przypisanie jego identyfikatora zmiennej muteks muteks:=createmutex(nil, False, MojMuteks ); if WaitForSingleObject(muteks, 0)<>wait_TimeOut sprawdzenie, czy muteks jest then begin w posiadaniu innego programu Application.Initialize; Application.CreateForm(TForm1, Form1);... Application.Run end end. PP-14(24 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Użycie muteksu Jeżeli dwa razy uruchomimy program z podanym kodem, zobaczymy, że tworzy on nową tymczasową kopię programu (na pasku zadań pojawi się piktogram), a następnie po upływie czasu podanego w wywołaniu funkcji WaitForSingleObject usuwa ją. Nie wiadomo jednak w jaki sposób włączyć istniejący egzemplarz programu. Użycie muteksu eliminuje problem innego programu, którego aktualnie aktywne (może jedyne) okno będzie miało taką samą nazwę, jak okno programu z muteksem. PP-14(25 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien Aby wyszukać określone okno główne w środowisku Windows można użyć funkcji API EnumWindows. Funkcja ta, zwana funkcją wyliczeniową, wymaga podania jako parametru wskaźnika do funkcji (zwanej funkcją zwrotną lub funkcją powtórnego wywołania ang. callback function): EnumWindows (wskaźnik-do-funkcji-zwrotnej, parametr) gdzie parametr oznacza 32-bitowa wartość przekazywana do funkcji zwrotnej (w naszym problemie wartość ta jest nieistotna przyjmujemy 0). PP-14(26 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien Koncepcja polega na tym, żeby funkcję zwrotną wywołać dla każdego elementu na liście głównych okien środowiska Windows) aż do końca listy lub przyjęcia przez tę funkcję wartości False, co zakończy także działanie funkcji wyliczeniowej EnumWindows. Dla naszych celów funkcja zwrotna może mieć następującą postać (nielokalna zmienna ModuleName zawiera nazwę zbioru wykonywalnego bieżącego programu, a FoundWnd identyfikator odszukanego okna): PP-14(27 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien function EnumWndProc (hwnd : THandle; Param : Cardinal) : Bool; stdcall; var ClassName, WinModuleName : string; WinInstance : THandle; begin Result:=True; SetLength (ClassName, 100); GetClassName (hwnd, PChar(ClassName), Length(ClassName)); ClassName:=PChar(ClassName); if ClassName=TForm1.ClassName then begin pobranie nazwy klasy o identyfikatorze hwnd dopasowanie długości zakładamy, że główne okno nazywa się Form1 SetLength (WinModuleName, 200); PP-14(28 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien WinInstance:=GetWindowLong (hwnd, GWL_HINSTANCE); uzyskanie identyfikatora egzemplarza programu GetModuleFileName (WinInstance, PChar(WinModuleName), Length(WinModuleName)); pobranie nazwy zbioru wykonywalnego dotyczącego danego egzemplarza programu WinModuleName:=PChar(WinModuleName); if WinModuleName=ModuleName then begin FoundWnd:=hwnd; end end {EnumWndProc}; Result:=False end porównanie nazw zbiorów wykonywalnych zakończenie wyliczania PP-14(29 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien Jeśli w podanej funkcji nazwa zbioru programowego głównego okna (WinModuleName) odpowiada nazwie bieżącego programu (ModuleName), możemy być pewni, że odszukaliśmy poprzedni egzemplarz tego samego programu. W takim przypadku należy spowodować uaktywnienie poprzedniego egzemplarza programu. Odpowiedni kod może mieć postać PP-14(30 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien... var hmutex, FoundWnd : THandle; ModuleName : string;... begin hmutex:=createmutex(nil, False, MyMutex2 ); if WaitForSingleObject(hMutex, 0)<>wait_TimeOut then begin Application.Initialize; Application.CreateForm(TForm1, Form1);... Application.Run end PP-14(31 z 76)

end. Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien else begin SetLength (ModuleName, 200); GetModuleFileName (HInstance, PChar(ModuleName), Length(ModuleName)); pobranie nazwy zbioru wykonywalnego bieżącego programu ModuleName:=PChar(ModuleName); // dopasuj dlugosc end EnumWindows (@EnumWndProc, 0); odszukanie głównego okna poprzedniego egzemplarza programu if FoundWnd<>0 then SetForegroundWindow (FoundWnd) PP-14(32 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien Wywołanie funkcji SetForegroundWindow nie powoduje uaktywnienia głównego okna poprzedniego egzemplarza programu, gdy zostało ono zminimalizowane (zob. pierwszy przypadek). Problem ten można rozwiązać przez spowodowanie, by poprzedni egzemplarz przywrócił swoje główne okno wskutek wysłania odpowiedniej wiadomości z bieżącego egzemplarza. PP-14(33 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien Instrukcję if FoundWnd<>0 then SetForegroundWindow (FoundWnd) wystarczy zastąpić przez if FoundWnd<>0 then begin if IsIconic(FoundWnd) then PostMessage (FoundWnd,wm_User, 0, 0); SetForegroundWindow (FoundWnd) end PP-14(34 z 76)

Sprawdzanie obecności poprzedniego egzemplarza programu Przeszukiwanie listy okien i w kodzie okna głównego dodać metodę obsługi tej wiadomości: type TForm1 = class(tform)... public procedure WMUser (var msg : TMessage); message wm_user; end;... procedure TForm1.WMUser (var msg : TMessage); begin Application.Restore end; PP-14(35 z 76)

... prezentacja... PP-14(36 z 76)

Wielowątkowość Pojęcie procesu i wątku Wykonanie programu, który ma swój kod i dane, zajmuje własną, wirtualną przestrzeń adresową oraz korzysta z zasobów systemowych, nazywa się procesem. Na proces może składać się jeden lub kilka wątków. Wątek jest podstawową jednostką, której system operacyjny przydziela czas procesora. Jest on niezależną ścieżką wykonywania części kodu programu wewnątrz procesu. PP-14(37 z 76)

Wielowątkowość Pojęcie procesu i wątku Wątek może wykonać dowolną część kodu programu, w tym część, która jest już wykonywana przez inny wątek. Wszystkie wątki programu wykorzystują tę samą wirtualną przestrzeń adresową, zmienne globalne i zasoby systemowe procesu. Oprócz tego każdy wątek posiada swoje własne rejestry, własny stos i własny mechanizm wejścia, w tym własną kolejkę wiadomości. PP-14(38 z 76)

Wady wielowątkowości: Wielowątkowość Pojęcie procesu i wątku powoduje, że program działa wolniej, chyba że jest kilka procesorów i system operacyjny może rozdzielić wątki między nimi, źle napisane programy wielowątkowe mogą działać wolniej w systemach wieloprocesorowych niż w systemie z jednym procesorem, gdyż synchronizacja wątków zużywa o wiele więcej zasobów w systemach wieloprocesorowych, programy wielowątkowe muszą synchronizować dostęp do wspólnych zasobów i pamięci, co powoduje, że jest je o wiele trudniej napisać. PP-14(39 z 76)

Zalety wielowątkowości: Wielowątkowość Pojęcie procesu i wątku można uruchomić wątek w tle, pozwalając użytkownikowi na obsługę programu, można spowodować, że jeden wątek będzie działał szybciej niż inne przez ustawienie jego priorytetu, można regulować dostęp różnych wątków do zasobów, przydzielać lokalną pamięć dla każdego wątku i uruchamiać wiele wątków tego samego typu. Operacja, którą warto umieścić w wątku drugoplanowym to taka, której wykonanie zajmuje procesorowi dużo czasu i jest dość odizolowana jeśli chodzi o dostęp do danych. PP-14(40 z 76)

Wielowątkowość Zmienne wątkowe W module System zdefiniowano funkcję BeginThread i procedurę EndThread, które dotyczą obsługi wątków. Zwykle funkcji tej i procedury nie używa się bezpośrednio, a zamiast tego korzysta się z klasy TThread określonej w module System.Classes. Z obsługą wątków są związane zmienne wątkowe, które deklaruje się następująco: threadvar sekwencja-deklaracji Deklaracja jakiejś zmiennej jako wątkowej oznacza, że jest ona zmienną lokalną w ramach wątku (wartości przypisane jej w wątku są tracone po zakończeniu wykonywania wątku). PP-14(41 z 76)

Wielowątkowość Klasa TThread Służy do kontrolowania wątków. Nie używa się jej bezpośrednio, gdyż jest to klasa z metodą abstrakcyjną Execute. Aby stosować wątki, zawsze tworzy się klasę potomną od TThread i wykorzystuje odpowiednie elementy tej klasy bazowej: # konstruktor Create o wywołaniu Create (zawieszenie) gdzie parametr jest typu Boolean decyduje o tym, czy uruchomić wątek natychmiast, czy też zawiesić go na później, PP-14(42 z 76)

Wielowątkowość Klasa TThread # bezparametrowe metody synchronizacji (publiczne) Resume Suspend Terminate WaitFor # własności Priority rozpoczęcie (procedura) zawieszenie (procedura) przerwanie (funkcja) oczekiwanie (funkcja) priorytet typu wyliczeniowego: type TThreadPriority = (tpidle, tplowest, tplower, tpnormal, tphigher, tphighest, tptimecritical); PP-14(43 z 76)

# własności (cd.) Suspended Terminated Handle ThreadID Wielowątkowość Klasa TThread zawieszenie (Boolean) przerwanie (Boolean) (tylko do odczytu) (tylko do odczytu) # metody chronione (sekcja protected) Execute metoda abstrakcyjna (musi być zdefiniowana w każdej klasie potomnej, gdyż zawiera główny kod wątku), PP-14(44 z 76)

Wielowątkowość # metody chronione (cd.) Klasa TThread Synchronize ma na celu uniknięcie jednoczesnego dostępu do komponentów VCL, a jej wywołanie ma postać Synchronize (metoda) gdzie parametr metoda jest metodą klasową (wykonywaną dla głównego wątku) PP-14(45 z 76)

Wielowątkowość Przykłady Przykład 1 (wykorzystanie metody Synchronize) Wątek służy do malowania kolorowych pikseli na formatce. W klasie wątku TPainterThread (klasa potomna klasy TThread) zdefiniowano metodę Execute (pokrywa ona metodę abstrakcyjną z klasy TThread) oraz metodę Paint, która umożliwia dostęp do obiektów VCL (dlatego jest ona wywoływana tylko z metody Synchronize). PP-14(46 z 76)

Wielowątkowość Przykłady Przykład 1 (wykorzystanie metody Synchronize) type TPainterThread = class (TThread) private X, Y : Integer; protected procedure Execute; override; procedure Paint; end; procedure TPainterThread.Paint; begin Form1.Canvas.Pixels[X,Y]:=clYellow end; PP-14(47 z 76)

Wielowątkowość Przykłady Przykład 1 (wykorzystanie metody Synchronize) procedure TPainterThread.Execute; begin Randomize; repeat X:=Random(Form1.ClientWidth); Y:=Random(Form1.ClientHeight); Synchronize (Paint) until Terminated end; PP-14(48 z 76)

Wielowątkowość Przykłady Przykład 1 (wykorzystanie metody Synchronize) Na formatce umieszczamy dwa przyciski: jeden uruchamiający wątek i drugi zatrzymujący wątek (oprogramowujemy zdarzenia OnClick tych przycisków). W metodzie obsługi zdarzenia OnClick pierwszego przycisku umieszczamy wywołanie konstruktora: PT:=TPainterThread.Create (False); pole prywatne w klasie opisującej formatkę powoduje natychmiastowe uruchomienie wątku PP-14(49 z 76)

Wielowątkowość Przykłady Przykład 1 (wykorzystanie metody Synchronize) W metodzie obsługi zdarzenia OnClick drugiego przycisku wywołujemy metodę Terminate: PT.Terminate; Można jeszcze dodać metodę obsługi myszki, np. aby po naciśnięciu jej klawisza wymazywane były piksele wokół punktu usytuowania kursora myszki. p r e z e n t a c j a... PP-14(50 z 76)

Wielowątkowość Przykłady Przykład 2 (synchronizacja za pomocą metod Lock i Unlock) Ten sam przykład, co poprzednio, ale z wykorzystaniem metod blokujących klasy TCanvas: Lock i Unlock. Za pomocą tych metod uzyskujemy dostęp do powierzchni formatki przez jej blokadę (metoda Synchronize jest wówczas niepotrzebna, co znacznie przyspiesza działanie kodu). Kod metody Execute będzie robił wszystko po zablokowaniu powierzchni formatki. PP-14(51 z 76)

Wielowątkowość Przykłady Przykład 2 (synchronizacja za pomocą metod Lock i Unlock) procedure TPainterThread.Execute; var X, Y : Integer; begin Randomize; repeat X:=Random(Form1.ClientWidth); Y:=Random(Form1.ClientHeight); with Form1.Canvas do begin Lock; try Pixels[X,Y]:=clBlue; finally Unlock end end until Terminated end; p r e z e n t a c j a... PP-14(52 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Program będzie wyświetlał piksele w czterech różnych kolorach (na ekranie będzie to widoczne jako wyświetlanie linii). Tworzymy nową wersję klasy TPainterThread oraz definiujemy konstruktor, którego zadaniem będzie zainicjowanie prywatnego pola Color i wywołanie konstruktora przodka z utworzeniem wątku w stanie zawieszenia: PP-14(53 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) type TPainterThread = class (TThread) private Color : Integer; SuspendRequest : Boolean; protected procedure Execute; override; procedure DeleyedSuspend; public constructor Create (Col : TColor); end; PP-14(54 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) constructor TPainterThread.Create (Col : TColor); begin Color:=Col; inherited Create (True) end; Metodę Execute napiszemy tak, by po kolei przechodziła przez wszystkie wiersze, ustawiając kolor każdego piksela. PP-14(55 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) procedure TPainterThread.Execute; var X, Y, X1 : Integer; begin X:=0; Y:=0; repeat X1:=X+1; X:=X1 mod 250; Y:=Y+X1 div 250; Y:=Y mod Form1.ClientHeight; Form1.Canvas.Lock; PP-14(56 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) try Form1.Canvas.Pixels[X,Y]:=Color; finally Form1.Canvas.Unlock end; if SuspendRequest then begin Suspend; SuspendRequest:=False end until Terminated end; znaczenie tej instrukcji wyjaśniono dalej PP-14(57 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Na formatce umieszczamy cztery komponenty CheckBox i cztery suwaki (komponenty TrackBar), za pomocą których będziemy ustalać priorytety wątków. Ponadto deklarujemy lokalną tablicę przechowującą cztery obiekty wątków: type TForm1 = class (TForm)... private PT : array [1..4] of TPainterThread; end; PP-14(58 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Tablica PT jest inicjowana w chwili tworzenia formatki (przez metodę obsługi zdarzenia OnCreate): procedure TForm1.FormCreate (Sender : TObject); begin PT[1]:=TPainterThread.Create (clred); PT[2]:=TPainterThread.Create (clblue); PT[3]:=TPainterThread.Create (clgreen); PT[4]:=TPainterThread.Create (clblack) end; PP-14(59 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Dotychczasowy kod tworzy cztery wątki jako zawieszone. Uruchamiane są one po zaznaczeniu odpowiedniego pola wyboru (komponentu CheckBox) i ponownie zawieszane po usunięciu zaznaczenia: procedure TForm1.CheckBoxClick (Sender : TObject); begin if (Sender as TCheckBox).Checked then PT[(Sender as TCheckBox).Tag].Resume else PT[(Sender as TCheckBox).Tag].DeleyedSuspend end; Aby nie pisać oddzielnych metod dla każdego komponentu CheckBox, własności Tag każdego z nich przypisano numer odpowiedniego wątku. PP-14(60 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Metoda DeleyedSuspend ustawia pole wątku SuspendRequest (typu Boolean) i wartość ta jest sprawdzana na końcu cyklu wewnątrz kodu wątku (metody Execute) zob. bliżej. procedure TForm1.RedClick (Sender : TObject); begin if (Sender as TCheckBox).Checked then PT[(Sender as TCheckBox).Tag].Resume else PT[(Sender as TCheckBox).Tag].DeleyedSuspend end; PP-14(61 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Metoda DeleyedSuspend ustawia pole wątku SuspendRequest (typu Boolean) i wartość ta jest sprawdzana na końcu cyklu wewnątrz kodu wątku (metody Execute) zob. bliżej: procedure TPainterThread.DeleyedSuspend; begin SuspendRequest:=True end; Zastosowana konstrukcja zapewnia, że metoda Suspend jest wywoływana tylko wtedy, gdy wątek nie blokuje tła formatki (w przypadku wywołania metody Suspend podczas takiej blokady zostałyby zatrzymane wszystkie wątki). PP-14(62 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) Własności Tag używamy też w przypadku suwaków, które ustawiają aktualny priorytet wątków (dzięki temu wystarczy napisać jedną metodę obsługi zdarzenia OnChage): procedure TForm1.TrackBarChange (Sender : TObject); begin PT[(Sender as TTrackBar).Tag].Priority:= TThreadPriority((Sender as TTrackBar).Position) end; PP-14(63 z 76)

Wielowątkowość Przykłady Przykład 3 (priorytety wątków) W metodzie tej w celu ustawienia priorytetu wykonujemy konwersję aktualnego położenia suwaka (Position) na odpowiednią wartość typu wyliczeniowego TThreadPriority, a następnie wykorzystujemy otrzymaną wartość do ustawienia priorytetu właściwego wątku, zgodnie z własnością Tag. procedure TForm1.TrackBarChange (Sender : TObject); begin PT[(Sender as TTrackBar).Tag].Priority:= TThreadPriority((Sender as TTrackBar).Position) end; p r e z e n t a c j a... PP-14(64 z 76)

Wielowątkowość Przykłady Wiemy już, że istnieją dwa typowe rozwiązania synchronizacji wątku z resztą programu: użycie metody Synchronize oraz użycie metod Lock i Unlock, które posiadają niektóre komponenty VCL. Jeżeli wątek powinien czekać aż zakończy się inny wątek, może wywołać metodę WaitFor obiektu odpowiadającego wątkowi, który właśnie powinien się zakończyć. PP-14(65 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Zadaniem programu jest zliczenie liczby wystąpień czterech podanych znaków w tekście komponentu Memo. Znaki podaje się w polu wejściowym (komponent Edit). Każdy z czterech znaków jest szukany przez inny wątek utworzony przez wątek główny. Dodatkowo każdy wątek wyświetla wskaźnik postępu (komponent ProgressBar), który ilustruje rozmiar tekstu już przeszukanego. PP-14(66 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) pole do wpisania poszukiwanych znaków przycisk rozpoczęcia procesu przycisk do wczytania tekstu (z dysku) wskaźniki postępu dla każdego znaku (każdy znak jest szukany przez inny wątek) pole Memo zawierające przeszukiwany tekst PP-14(67 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Główną klasą programu jest klasa TFindThread: type TFindThread = class (TThread) protected liczba przeczytanych znaków Progr : Integer; procedure UpdateProgress; procedure Execute; override; public wynik obliczeń Found : Integer; przechowanie LookFor : Char; poszukiwanego znaku Progress : TProgressBar; wskaźnik postępu end; PP-14(68 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Główna metoda wątku Execute: procedure TFindThread.Execute; var i, j : Integer; line : string; begin Found:=0; with Form1.Memo1 do for i:=0 to Lines.Count 1 do begin line:=lines[i]; for j:=1 to Length(line) do if line[j]=lookfor then Inc (Found); Progr:=i+1; Synchronize (UpdateProgress) end end; PP-14(69 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Cztery kopie wątku są aktywowane przez wątek główny obiekt klasy TMultiFind: type TMultiFind = class (TThread) protected Progr : Integer; procedure UpdateProgress; do wypisania wyników liczbowych procedure Execute; override; procedure Show; public LookFor, Output : string; Progresses : array [1..5] of TProgressBar; end; PP-14(70 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Metoda Execute tej klasy szuka znaków łańcucha LookFor używając czterech obiektów TFindThread: procedure TMultiFind.Execute; var finders : array [1..4] of TFindThread; i : Integer; begin for i:=1 to 4 do begin finders[i]:=tfindthread.create(true); utworzenie wątku finders[i].lookfor:=lookfor[i]; finders[i].progress:=progresses[i+1]; finders[i].resume rozpoczęcie wykonywania end; PP-14(71 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Metoda Execute tej klasy szuka znaków łańcucha LookFor używając czterech obiektów TFindThread: for i:=1 to 4 do begin finders[i].waitfor; oczekiwanie na zakończenie wątku Progr:=i; Synchronize (UpdateProgress) end; Output:= Found: ; tworzenie łańcucha z wynikami for i:=1 to 4 do Output:=Output+Format('%d %s, ', [finders[i].found, LookFor[i]]); Synchronize (Show);... tu trzeba dodać usunięcie wątków PP-14(72 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Przycisk Start uruchamia wątek, który z kolei natychmiast uruchamia wątki drugoplanowe: procedure TForm1.StartClick (Sender : TObject); var i : Integer; begin if Assigned(MainThread) then MainThread.Free; MainThread:=TMultiFind.Create(True); MainThread.Progresses[1]:=ProgressBar1; MainThread.Progresses[2]:=ProgressBar2; MainThread.Progresses[3]:=ProgressBar3; MainThread.Progresses[4]:=ProgressBar4; MainThread.Progresses[5]:=ProgressBar5; PP-14(73 z 76)

Wielowątkowość Przykłady Przykład 4 (oczekiwanie na wątek zastosowanie metody WaitFor) Przycisk Start uruchamia wątek, który z kolei natychmiast uruchamia wątki drugoplanowe: MainThread.Progresses[1].Max:=4; for i:=2 to 5 do MainThread.Progresses[i].Max:=Memo1.Lines.Count; for i:=1 to 5 do MainThread.Progresses[i].Position:=0; MainThread.LookFor:=Edit1.Text; MainThread.Resume rozpoczęcie wykonywania głównego wątku end; PP-14(74 z 76)

Powodzenia w dokończeniu programu we własnym zakresie... Szkielet programu, zawierający przedstawione elementy, jest do pobrania ze strony www. PP-14(75 z 76)

... i to by było na tyle... PP-14(76 z 76)