2010-09-27 15 views
6

Nigdy wcześniej nie pracowałem z wątkami, a teraz próbuję utworzyć wątek z zapytaniem, aby sprawdzić stan bazy danych. Zapytanie jest następujące:jak pisać i wykonywać wątek

select (*) as DBCount from v$datafile where status in 'OFFLINE';.

Ta kwerenda zwraca całkowitą liczbę wszystkich baz danych, które są w trybie offline. Teraz chcę utworzyć wątek w Delphi, który wykona to zapytanie w tle mojej aplikacji po uruchomieniu i wyświetleniu wyników na etykiecie.

+0

Usunąłem tag pthread, ponieważ nie jest on kompatybilny z tagiem delphi. – mghie

Odpowiedz

0

W Delphi jest klasa TThread. Możesz stworzyć taki wątek za pomocą prostego kreatora z Delphi IDE (w Turbo Delphi: Plik-> Nowy-> Projekty Delphi-> Pliki Delphi-> Thread Obcjet). W jego konstruktorze utwórz połączenie z bazą danych, aw metodzie Execute możesz utworzyć pętlę bazy danych zapytań, zaktualizować niektóre zmienne globalne (NIE zadeklarowane jako threadvar) i przespać trochę czasu.

+2

Umieszczenie wyniku w 'threadvar' uniemożliwi uzyskanie przez inny wątek wyniku. Jak to będzie przydatne? – mghie

+1

upps, przepraszam, mój błąd, oczywiście powinna to być normalna zmienna. –

+0

Zastanawiam się, dlaczego ta odpowiedź została odrzucona (nawet pomimo threadvar), ponieważ uważam, że jest pomocna i daje OP miejsce do rozpoczęcia i rozpoczęcia czytania. Byłoby wspaniale, gdyby SO pozwalało tylko na zmotywowane downvote ... – Remko

7

Wielowątkowość jest trudna. Być może lepiej wykorzystaj prostą strukturę wątków, taką jak AsyncCalls.

Obserwuje StackOverlow wątki mogą dać Ci więcej informacji o tym, jak rozwiązać problem:

Delphi - Threading frameworks

How Do I Choose Between the Various Ways to do Threading in Delphi?

Delphi thread that waits for data, processes it, then resumes waiting

+0

Innym ładnym Threading Framework jest OmniThreadLibrary gabr: P http://otl.17slon.com/ – Remko

+0

@Remko: Jest on zawarty w wątkach, które miałem na myśli. – gabr

0

Tutaj można znaleźć dyskusję na temat korzystania wątki na bazie danych.

Simple Thread Sample Delphi

Istnieją pewne kodu, które mogą być przydatne dla Ciebie.

Pozdrawiam.

1

Jest to dość łatwe do zrobienia przy użyciu AsyncCalls. Załóżmy, że Twój kod niegwintowane wygląda (pomijając wszystko obsługę błędów):

Query := 'select (*) as DBCount from...'; 
ExecuteSQL(SqlConnection,Query); 
SqlResult := GetSqlResult(SqlConnection); 
SqlRow := GetSqlRow(SqlResult); 
MyLabel.Text := SqlRow[0]; 
...Go on to do other things... 

Gdzie druga linia jest blokowanie (oczekiwanie na serwer odpowiedzieć). Nowy kod będzie wyglądać następująco:

uses AsyncCalls;  //added to your existing uses statement 
... 
procedure DoesSomething(); 
var Thread: TAsyncCall;    //your interface to AsyncCalls 
    procedure AsyncSqlCall();    //this is a LOCAL procedure 
    Query := 'select (*) as DBCount from...'; 
    ExecuteSQL(SqlConnection,Query); 
    SqlResult := GetSqlResult(SqlConnection); 
    SqlRow := GetSqlRow(SqlResult); 
    EnterMainThread; 
    try 
     Assert(GetCurrentThreadId = MainThreadId); 
     MyLabel.Text := SqlRow[0]; 
    finally 
     LeaveMainThread;   
    end; 

begin       //this begins proc DoSomething() 
    ... 
    Thread := LocalAsyncCall(@AsyncSqlCall); 
    ...Go on to do other things... 
end; 

Wszystko zrobiliśmy jest umieścić blokowania połączeń SQL w lokalnej proc i powiedział AsyncCalls wykonać go w innym wątku, podczas gdy główny wątek kontynuuje wykonywanie. Jedyną trudną częścią było użycie VCL, który nie jest bezpieczny dla wątków. Miałem więc bezpieczną linię w głównym wątku.

Jeśli w pewnym momencie trzeba być pewien wątek asynchroniczny został zakończony, należy wykonać tę linię do zablokowania głównego wątku do AsyncSqlCall kończy:

Thread.sync; 

Naprawdę miłą rzeczą jest to, że AsyncCalls obsługuje wszystkie rzeczy dotyczące tworzenia puli wątków, tworzenia wątków itp. Chociaż nie pokazano tego w tym przykładzie, możesz przekazać zmienne do wątku i zwrócić wartość. Nie musisz używać lokalnego procesu, ale dzięki temu uzyskujesz dostęp do wszystkich lokalnych zmiennych. Możesz zrobić to wszystko globalnie, a następnie uruchomić wątek Async w jednej procedurze i przetestować jego zakończenie w innym.

Ograniczenia:

Twój wątek asynchroniczny nie może dotykać (odczyt lub zapis) niczego poza własnymi zmiennymi, a główny wątek nie wolno ich dotykać, podczas gdy nitka asynchroniczny pracuje. TY musisz zakodować to w ten sposób. Nic nie powstrzyma cię od stworzenia totalnego chaosu. W powyższym przykładzie twój główny wątek nie może dotykać Query, SqlConnection, SqlResult i SqlRow. Jeśli jakakolwiek część twojego kodu użyła jednej z tych zmiennych przed wywołaniem Thread.sync, twój kod by zadziałał - ale wyrzuć wyjątki w dziwnych miejscach, których się nie spodziewałeś. Tak więc zachowaj to proste.

Twój wątek Async nie może używać VCL. Powyższy przykład pokazuje jeden z kilku sposobów bezpiecznego obejścia tego ograniczenia.

Wreszcie:

AsyncCalls nie jest pełna framework Multi-Threading. Jest to tylko sposób asynchronicznego wywoływania funkcji procs & (tj. Bez czekania). Nie próbuj przesuwać go zbyt daleko - przez co rozumiem, nie próbuj uczynić go podstawą w pełni wielozadaniowego programu.