Wątek eksportujący pliki PDF nie działa

0

Jako, że potrzebuję programu, który musi wygenerować setki plików na podstawie danych z arkusza kalkulacyjnego, skorzystałem z tutorialu Wątki i utworzyłem sobie wątek z dwiema funkcjami, jedną czytającą arkusz i drugą eksportującą PDF-y, żeby nie robił tego wszystkiego w głównym wątku:

Watek = class(TThread)
  private
    nr : integer;
  protected
    function czytaj(src: string) : integer;
    procedure eksport(l: integer; wzor: string; doc:string);
    procedure Execute; override;
  end;

Tak jak w tutorialu, jeden przycisk uruchamia wątek metodą Resume, drugi go zatrzymuje metodą Suspend, a inicjalizowany jest za pomocą Watek.Create(True) w bloku initialization. Samo Execute wygląda tak:

procedure Watek.Execute;
begin
  nr := czytaj('D:\karty.xls');
  eksport(nr, 'D:\karta.fr3', 'D:\');
end;

Problem polega na tym, że po kliknięciu na "start" (przycisk z Resume) nic się nie dzieje, nie w stylu wyskakiwania ostrzeżeń o błędzie ale program po prostu nic nie robi. Nie może to być wina samych funkcji gdyż wywoływane osobno (bez wątku) działają prawidłowo i generują dokumenty dokładnie tak jak powinny. Sam wątek też wiem że się na pewno uruchamia bo gdy np. wstawić do Execute jakąś dodatkową komendę po begin (np. ShowMessage()) to program ją normalnie wykonuje po kliknięciu na "start", chyba że się ją wstawi po którejś z tych funkcji, wtedy też nic nie robi tak jakby tej funkcji nie potrafił wykonać. Co ciekawe, po kliknięciu na "stop" wyskakuje "Thread Error. Odmowa dostępu (5)" pomimo że wszystko jest tak jak w tutorialu. Wiem, że musiałem coś sknocić z wywoływaniem tych funkcji w tym wątku, ale nie mam, pojęcia, jak to powinno być w sposób prawidłowy. Ma ktoś jakieś pomysły?

0
mychal napisał(a)

Daj kod z sekcji initialization oraz obsługi zdarzeń przycisków o których mowa

Praktycznie to jest wszystko:

procedure TForm1.Button5Click(Sender: TObject);
begin
  wtk.Resume;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  wtk.Suspend;
end;

initialization
  wtk := Watek.Create(True);

end.

(wtk to rzecz jasna instancja Watek zadeklarowana w var)

0

Suspend oraz Resume są deprecated. Cytat z dokumentacji:

Call Create to create a thread in an application. If CreateSuspended is false, Execute is called immediately after the constructor. If CreateSuspended is true, Execute is not called until after the Start method is called.

Podsumowując, nie wywołujesz metody Start.

0

Nie wiem czy zdajesz sobie sprawę że ten Execute zrobi jeden przebieg i na tym koniec.

0
_13th_Dragon napisał(a):

Nie wiem czy zdajesz sobie sprawę że ten Execute zrobi jeden przebieg i na tym koniec.

W sumie o to chodzi, żeby tylko jeden raz wyeksportował te PDF-y w osobnym wątku i żeby np. można było bez problemu w każdej chwili przerwać jeśli np. miałby eksportować tysiące plików i długo by to trwało...

mychal napisał(a):

Podsumowując, nie wywołujesz metody Start.

"[Error] Unit1.pas(220): Undeclared identifier: 'Start'"

0

na zmiennej wtk oczywiście...

Ale to właśnie jest wtk.Start; tyle że u mnie może to akurat nie działa bo właśnie zauważyłem że to jest Delphi 7...

0

Następnym razem od razu napisz jaką wersją Delphi dysponujesz oraz ogarnij się, skoro nawet nie wiedziałeś z jakiego środowiska korzystasz... W Delphi7 klasa TThread nie posiada metody Start, więc powinieneś użyć tych opisanych we wspomnianym artykule; Oczywiście przedebuguj sobie kod i sprawdź które instrukcje się wykonują, a które nie; Ewentualnie pobaw się w osobnym programie, stworzonym jedynie do przetestowania wykorzystania wątków;

Zobacz sobie do tego artykułu - jest w nim więcej szczegółów i przykładów.

1

Sprawdź czy metody czytaj i eksport nie sypią wyjątkami.

0

Dobra, spróbowałem jedną z funkcji odpalić poza wątkiem a tylko drugą zostawić i tym razem zadziałało, okazało się że brakowało w niej jakiejś funkcji CoInitialize() która akurat jest potrzebna podczas działania w wątku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1