Programuję aplikację wielowątkową. Mam dwa wątki. Włączony służy do przesyłania niektórych danych z urządzenia do globalnego bufora danych, a drugi do zapisywania tych danych do pliku.Najlepsza praktyka, jak czekać na dane w wątku i zapisać go w pliku?
Dane z urządzenia do bufora przesyłają się asynchronicznie. Celem drugiego wątku powinno być oczekiwanie na zapisanie określonej ilości danych w głównym buforze danych i na koniec zapisanie pliku do pliku.
Cóż, pierwszy wątek znajduje się w DLL, a drugi w głównej aplikacji. Tymczasowo rozwiązuję to z wydarzeniami. Pierwszy wątek przesyła dane z urządzenia do głównego bufora danych i zlicza dane, a po przekazaniu określonej ilości danych ustawia zdarzenie. Drugi oczekuje na sygnalizację zdarzenia, a gdy jest uruchomiony, uruchamia kod dla magazynu danych. Proste, ponieważ to działa.
Thread1.Execute:
var DataCount, TransferedData: Integer;
DataCounter := 0;
while not Terminted do
begin
TransferData(@pData, TransferedData);
Inc(DataCounter, TransferedData)
if DataCounter >= DataCountToNotify then SetEvent(hDataCount);
end;
Thread2.Execute:
hndlArr[0] := hDataCount;
hndlArr[1] := hTerminateEvent;
while (not Terminated) do
begin
wRes := WaitForMultipleObjects(HandlesCount, Addr(hndlArr), false, 60000);
case wRes of
WAIT_OBJECT_0:
begin
Synchronize(WriteBuffer); // call it from main thread
ResetEvent(hndlArr[0]);
end;
WAIT_OBJECT_0 + 1:
begin
ResetEvent(hTerminateEvent);
break;
end;
WAIT_TIMEOUT: Break;
end;
end;
Teraz chciałbym zrobić drugi wątek bardziej niezależne ... więc mogę zrobić wiele wystąpień drugiego wątku i nie trzeba czekać na pierwszym wątku. Chciałbym przenieść część kodu zliczającą dane z pierwszego wątku do drugiego, więc nie będę już potrzebować liczenia danych w pierwszym wątku. Pierwszy z nich będzie przeznaczony wyłącznie do celów przesyłania danych.
Chciałbym użyć drugiego jako licznika danych i do przechowywania danych. Ale teraz będę musiał zapętlić i ciągle sprawdzać ręcznie dla określonej ilości danych. Gdybym miał pętlę while, będę musiał dodać trochę snu, więc drugi wątek nie zmniejszy wydajności komputera, ale nie wiem, jak długo powinienem spać, podczas gdy prędkość transferu danych w wątku początkowym nie jest stała, a zatem szybkość zliczania w drugim wątku Bedzie się różnić.
Zgaduję, że ten przykładowy kod nie jest dobre:
Thread2.Execute:
var DataCount: Integer;
DataIdx1 := GetCurrentDataIdx;
while (not Terminated) do
begin
if (GetCurrentDataIdx - DataIdx1) >= DataCountToNotify then
begin
Synchronize(WriteBuffer);
DataIdx1 := GetCurrentIdx;
end;
sleep(???);
end;
Więc moje pytanie brzmi: co jest najlepszym sposobem, aby rozwiązać ten problem z liczeniem danych i przechowywanie go w drugim wątku? Jakie są twoje doświadczenia i sugestie?
Dlaczego wymuszasz zapis pliku do głównego wątku, 'Synchronizuj (WriteBuffer)'? Nie rozumiem, w jaki sposób uda ci się pomnożyć drugi wątek i zachować kolejność zapisu w jednym pliku. –
Wątek zostanie pomnożony, ale dane będą przechowywane w różnych plikach. Nigdzie nie napisałem, że napiszę to do tego samego pliku. Moim celem jest posiadanie wielu kontrolek, które są w stanie przechowywać dane z tego samego źródła do różnych plików. – Nix
Dobrze wiedzieć, ponieważ odpowiedź będzie zależała od tych informacji. Wciąż zastanawiam się, dlaczego zapis pliku musi być egzekwowany do głównego wątku. –