CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Synchronizacja dla wątków

Synchronizacja dla wątków

dział ogólny

Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 19:10

Witam ponownie,
wiec jest taki problem - w głównym oknie programu jest komponent TListView zawierający listę listę no 2000 adresów stron na które powinny zastać wywołane w celu pobrania z nich kodu HTML do jakieś operacji na nim. Żądania HTTP metodą GET realizuje za pomocą INDY w w pętli w wątku przykładowo:
KOD cpp:     UKRYJ  
void __fastcall MyWatek::PobierzStart()
{
    ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[0] = "Start...";
    this->Edit1->Text = this->odwiedzony + 1;
    this->Start = GetTickCount();
}
//---------------------------------------------------------------------------
void __fastcall MyWatek::Execute()
{
    this->nrNaListViev = 0;
    TIdHTTP *IdHTTP1  = new TIdHTTP(NULL);
    for(int jj = 0; jj < ListView1->Items->Count; jj++)
    {
        this->nrNaListViev = jj;
        this->zadanyUrl = ListView1->Items->Item[jj]->Caption;
        Synchronize(&PobierzStart);
        try
        {
            IdHTTP1->HandleRedirects = true;
            IdHTTP1->ConnectTimeout = 5000;
            IdHTTP1->ReadTimeout = 5000;
            IdHTTP1->AllowCookies = true;
            this->kodHtml = Utf8ToAnsi(IdHTTP1->Get(this->zadanyUrl));
            this->kodHttp = IdHTTP1->ResponseText;
            Synchronize(&PobierzStop);

        }
        catch(EIdSocketError &e)
        {
            this->kodHttp = e.Message.Trim();
            Synchronize(&PobierzStop);
        }
        catch(Exception &exception)
        {
            this->kodHttp = exception.Message;
            Synchronize(&PobierzStop);
        }
    }
    delete IdHTTP1;    IdHTTP1 = NULL;
}
//---------------------------------------------------------------------------
 void __fastcall MyWatek::PobierzStop()
{
    ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[0] = this->kodHttp;
    this->End = GetTickCount();
    ListView1->Items->Item[this->nrNaListViev]->SubItems->Strings[1] = FloatToStr((this->End - this->Start) / 1000) + " s.";
}


I teraz problem polega jak uruchomić kolejne takie wątki i je zsynchronizować by następny wątek nie pobierał od zera, ale ostatniego nieodwiedzonego adresu na liście TListView czyli żeby odwiedzone adresy były pomijane.

Pozdrawiam
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 20:04

A nie możesz utworzyć zmiennej globalnej i po każdym wywołaniu wątku zmieniać jej stan o jeden, potem niech każdy nowy wątek sprawdza wartość tej zmiennej i rozpoczyna pobieranie nie od 0, lecz od wartości tej zmiennej.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 20:09

Ale jak zmienną np
TForm1 *Form1;
int nrPobrania; // zmienna globalna ??

przekazać do wątku ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 20:12

Jak to! Przecież to oczywiste. Deklarujesz zmienną nrPobranie w pliku nagłówkowym w sekcji public, np:

KOD cpp:     UKRYJ  
public:
        int nrPobrania;


W wątku odwołujesz się odpowiednio ją adresując:

KOD cpp:     UKRYJ  
Form1->nrPobrania;


To będzie zmienna publiczna, a globalną możesz zdefiniować na początku pliku nagłówkowego, np:

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

int nrPobrania;

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
Potem to już używasz jej bez adresowania na Form1, gdyż taka zmienna nie przynależy do żadnej klasy.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 20:25

Wiec w wątku w metodzie void __fastcall MyWatek::Execute() nie idzie odwołać się do zmiennej globalnej utworzonej
#pragma resource "*.dfm"
int nrPobrania;
TForm1 *Form1;
[C++ Error] WatekSprawdzaj.cpp(52): E2451 Undefined symbol 'nrPobrania'

I tak samo nie idzie odwołać się do zmiennej ustawione w
public: // User declarations
int nrJakiwywolal;
[C++ Error] WatekSprawdzaj.cpp(52): E2451 Undefined symbol 'Form1'

:(
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 20:27

Plik WatekSprawdzaj.cpp to nie jest plik źródłowy formularza?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 20:35

Plik Plik WatekSprawdzaj.cpp jest plikiem klasy wątku
Kod: Zaznacz cały
#include <vcl.h>
#pragma hdrstop

#include "WatekSprawdzaj.h"
#pragma package(smart_init)

__fastcall MyWatek::MyWatek(bool CreateSuspended)
   : TThread(CreateSuspended)
{
   FreeOnTerminate = true;
}

Kwestię rozwiązałem za pośrednictwem wizualnego komponentu Edit1 który zawiera startowa wartość -1 do którego watek ma dostęp bo przekazuje je jako pole klasy wątku. Następnie w wątku w metodzie wywoływanej na początku kolejnego przebiegu pętli MyWatek::PobierzStart() odczytuje wartość, zwiększam o jeden i zapisuje powrotem w Edit1. Ten problem z pewnością ma wiele rozwiązań, ale ten działa zgodnie z oczekiwaniem wiec chyba wystarczy :)
--------
Tylko nie wiem czy w pewnych okolicznościach jak np dwa działające wątki chciały by zapisać aktualną wartość do Edit1 wywoływanie tego zapisu wystarczy w metodzie uruchamianej w Synchronize(&PobierzStart); Czy też potrzeba "chronić się" za pomocą mutexu ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 20:53

Skoro użyłeś obiektu typu TEdit to przecież w ten sam sposób możesz użyć zmiennej, po co angażować do tego obiekt. Skoro masz klasę wątku to przecież możesz tam utworzyć sekcję private, dodać zmienną i korzystać z tej zmiennej w wątku. Coraz mniej zaczyna rozumieć co robisz.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 21:03

Cyfrowy Baron napisał(a): Skoro masz klasę wątku to przecież możesz tam utworzyć sekcję private, dodać zmienną i korzystać z tej zmiennej w wątku.
Skąd ma zmienna prywatna klasy wątku widzieć jaki jest nr wywołania realizowany w pozostałych wątkach :o Skoro wywoływane będą np 5 obiektów tej klasy = wątków działających jednocześnie.
Kod: Zaznacz cały
Watek1 = new MyWatek(true);
// Jakiś kod
Watek1->Resume();

Watek2 = new MyWatek(true);
// Jakiś kod
Watek3->Resume();

Watek3 = new MyWatek(true);
// Jakiś kod
Watek3->Resume();
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 21:11

Trochę inaczej to sobie wyobrażałem. Patrząc na twoją klasę wątku widzę, że lista ListView jest obiektem tworzonym dynamicznie w tej klasie, co oznacza, że za każdym razem jak wywołujesz nowy wątek to tworzysz nową listę, czyli każdy wątek ma własną listę, niezależną od list pozostałych wątków. W jaki sposób wypełniasz listę? Przecież te adresy na liście muszą się jakoś najpierw znaleźć.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 21:19

Cyfrowy Baron napisał(a):Trochę inaczej to sobie wyobrażałem. Patrząc na twoją klasę wątku widzę, że lista ListView jest obiektem tworzonym dynamicznie
CB Przecież ListView nie jest tworzony dynamicznie w klasie wątku bo było by to bez sensu tylko ListView1 jest komponentem w głównym formularzu wypełniony adresami stron do odwiedzenia. Do klasy wątku jest przekazywany też jako pole klasy :
Kod: Zaznacz cały
Watek = new MyWatek(true);
Watek->ListView1 = ListView1; // przekazuje jako pole klasy watku
// Dalszy kod
:?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 21:25

Przekazujesz go nie przez pole klasy wątku, lecz go rzutujesz. Przecież dokładnie w ten sam sposób możesz przekazać zmienną. Deklarujesz zmienną w klasie formularza oraz taką samą w wątku i rzutujesz ją na tą w wątku. Ponieważ wątki tworzysz w formularzu głównym to przed utworzeniem każdego wątku zmieniasz wartość zmiennej formularza i do zmiennej nowo tworzonego wątku przekazujesz nową wartość tej zmiennej. Skoro możesz przekazać do wątku cały obiekt, to dlaczego masz problemy z przekazaniem zmiennej.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 21:29

Widzę, że się w tej kwestii nie rozumiemy, ale mniejsze z tym, bo problem już mam rozwiązany.
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Cyfrowy Baron » środa, 29 września 2010, 21:38

To Ty najwyraźniej nie rozumiesz. Tak wywołujesz nowy wątek:

KOD cpp:     UKRYJ  
Watek = new MyWatek(true);
Watek->ListView1 = ListView1; // przekazuje jako pole klasy watku
// Dalszy kod


czyli w sekcji public klasy wątku musisz mieć taką deklarację:

KOD cpp:     UKRYJ  
public:
        TListView *ListView1;


dodaj jeszcze zmienną:

KOD cpp:     UKRYJ  
public:
        TListView *ListView1;
        int nr;
 


w pliku nagłówkowym klasy formularza deklarujesz podobną zmienną:

KOD cpp:     UKRYJ  
private:
        int nr;


W klasie formularza wywołujesz kolejne wątki przekazując im obiekt ListView1, więc tak samo przekazujesz zmienną, ale najpierw zmieniasz jej wartość:

KOD cpp:     UKRYJ  
  nr = 0
Watek1 = new MyWatek(true);
Watek1->ListView1 = ListView1; // przekazuje jako pole klasy watku
Watek1->nr = nr;
// Dalszy kod

nr++;
Watek2 = new MyWatek(true);
Watek2->ListView1 = ListView1; // przekazuje jako pole klasy watku
Watek2->nr = nr;
// Dalszy kod

nr++;
Watek3 = new MyWatek(true);
Watek3->ListView1 = ListView1; // przekazuje jako pole klasy watku
Watek3->nr = nr;
// Dalszy kod


Zauważ, że każdy kolejny wątek otrzymuje kolejną wartość zmiennej, która odpowiada liczbie utworzonych wątków, więc każdy nowy wątek zaczyna przeszukiwać listę od nowej pozycji zawartej w zmiennej nr. Nowy wątek otrzymuje wartość zmiennej, ale wartość zmiennej zmienia się w klasie formularza. Nie pojmuję jak można nie widzieć tej prostej zależności. :shock: :lol:
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Synchronizacja dla wątków

Nowy postprzez Darek_C++ » środa, 29 września 2010, 21:47

Tylko że to nadal nie rozwiązując tej kwestii o jaką chodziło.
1 Wątek pobiera adres this->zadanyUrl = ListView1->Items->Item[1]->Caption;
2 Wątek pobiera adres this->zadanyUrl = ListView1->Items->Item[2]->Caption;
3 Wątek pobiera adres this->zadanyUrl = ListView1->Items->Item[3]->Caption;
itd i co dalej :)
Ostatnio edytowano środa, 29 września 2010, 21:53 przez Darek_C++, łącznie edytowano 1 raz
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 27 gości