Dziwactwo z Tfilestream.write a może z dyskiem?

0

Witam.
Mam problem z działaniem Tfilestream, w zasadzie z jego małym potomkiem co tu raczej nie ma znaczenia. Problem polega na dziwnym działaniu metody write (która nie została przeze mnie przeciążona więc jest to metoda write klasy Tfilestream) w tylko jednym miejscu mojego kodu. Mianowicie zdarza się, że kod:

var st:string;
begin
// operacje na st oraz f, który jest obiektem klasy potomnej Tfilestream 
//wraz z przydzieleniem 60 bajtów pamięci na st
f.position:=70;
f.Write(st[1],60)// tu się "blokuje"
// inne operacje na f oraz st
end;

jest wykonywany przez kilka a nawet dwadzieścia kilka sekund. W tym czasie na maxa świeci się dioda dysków na obudowie kompa jakby były wykonywane nie wiadomo jakie operacje na dysku a to przecież tylko zapis 60-ciu bajtów. Przeglądałem ten kod pod debugerem w środowisku delphi i nie mam co do tego wątpliwości, że właśnie w oznaczonym miejscu

 f.Write(st[1],60) 

program staje na te kilka albo więcej sekund. Problem ten występuje nie zawsze, czasem zapis trwa ułamek sekundy tak jak należałoby się tego spodziewać jednak jeśli jest problem to tylko w tym jednym miejscu kodu. Testowałem to na różnych plikach testowych o rozmiarach od kilku do kilkuset megabyteów i w każdym z nich pojawia się od czasu do czasu ten efekt długotrwałego zapisu owych 60-ciu byteów w tym jednym miejscu mojego kodu.
Co może być tego przyczyną? Jak ten problem usunąć? To dość kłopotliwe jesli program miałby zatrzymywać się na tak długi czas z powodu jednego małego zapisu na dysk.

P.S Nie wiem czy to ma znaczenie ale ten kod powodujący długotrwały zapis wykonywany jest w destruktorze. Strumień f jest otwarty do odczytu i zapisu.

Z góry dziękuję za wszelkie konstruktywne posty i próby pomocy:-)

0

a st ma 60 znaków :>

0
 //wraz z przydzieleniem 60 bajtów pamięci na st 
0

to może jakiś kod, bo jak na razie to muszę na słowo uwierzyć. BTW jak przydzielasz te 60 znaków to czemu nie zapisujesz Length(st) tylko na sztywno 60 :>

0

ale jak to robisz ? jeżeli np przez setlength to to nic nie daje, nie da się tego typu sposobami przydzielić pamięci dla stringa bo ona jest dynamicznie przydzielana

0

Adamo jak to nic nie daje? Dla stringa właśnie tak przydziela się pamieć w delphi. A niby jak inaczej?
Poza tym próbowałem też (z braku lepszych pomysłow) zadeklarowac st:string[60] żeby miec krótkiego stringa i już mu nic nie przydzielac , jednak efekt jest ten sam.

Misiekd daje na sztywno 60 bo wiem że tam ma być przydzielone te 60. Zanim zapiszę to na dysk odpowiednio wypełniam owe 60 bajtów w stringu st. Niezaleznie od tego czy zadeklaruje go jako długiego stringa i przydziele pamiec przez setlength czy tez jako krótkiego ze z góry zadaną długością 60 to efekt jest ten sam.

Co do kodu to nie bardzo wiem co mógłbym pokazać. Dla testów wyciąłem z tej funkcji wszystko zostawiając jedynie

procedure Tpstr.statreset(i:integer);
var st:string[60];
begin
f.position:=10;// sorki poprzednio omyłkowo napisałem 70 choć to chyba bez znaczenia
f.Write(st[1],60)// tu się "blokuje"
exit;
// tu coś było ale się oczywiście nie wykonuje bo jest po exit;
end;

Procedsura statreset z owym feralnym kodem jest wywoływana na początku destruktora klasy Tpstr zaraz po utworzeniu strumienia f z dostępem do odczytu i zapisu.

0

A jak wygląda plik po tym zapisie, czy wszystko jest na swoim miejscu?

0

Plik jest w porządku i te 60 bajtów też jest takie jak być powinno. To funkcja writefile z modułu windows powoduje ten błąd. Program wykonując ją zatrzymuje się na dłuższy czas jak to pisałem wcześniej. Czasem nawet ponad minutę trwa zapis tych 60 bajtów. Porażka. Czy ktoś się z czymś takim zetknął? Sprawdzałem to na dwóch kompach z win xp i jest to samo.

0

nie możesz wstawić kawałka kodu od otwarcia streamu, przez nadanie wartości st po zapisanie i zamknięcie streamu wraz z deklaracją zmiennych tak, aby można to było odpalić i popatrzeć?

0

To jest bardzo prosta sytuacja. Napisałem ten kod oddzielnie bez żadnej klasy tak by operował na pliku odpowiednio dużym:

var  st:string[60];
       s:string;
begin
s:='nazwa dużego pliku'; 
f:=Tfilestream.Create(s,fmopenreadwrite);;
caption:='początek';
f.Position:=10;
f.Read(st[1],60);
f.Position:=10;
f.write(st[1],60);// w tym miejscu czasem się blokuje podczas wykonywania windows.writefile
caption:='koniec';
f.free;
end;

Na ogół wykonanie czegoś takiego to jest czas między pojawieniem sie "początek" na captionie formy a "koniec" jest niezauważalnym ułamkiem sekundy. Jednak zdarza mi się, jeśli plik jest duży tzn. ma kilkaset MB że ten czas to kilkadziesiąt sekund z efektem, o którym pisałem wcześniej , to jest zapaloną non-stop diodą dysku. Z moich testów widzę (choć nie wiem czy nie jest to złudzenie), że jeśli bezpośrednio wcześniej plik był czytany lub zapisywany w obszarach znacznie odległych od początku to ten czas się jeszcze wydłuża i efekt występuje częściej. To jest dziwna sytuacja, nie rozumiem jej. Test robię tak że podkładam pod ten kod różne duże pliki testowe. Czasem ten efekt pojawia mi sie częściej a czasem rzadziej.
Czy nikt się nigdy z czymś takim nie zetknął?

0

trochę potestowałem (pliki 700MB, 1,4GB i 4,3GB) zapisując 60 bajtów i 1024 bajty

i := GetTickCount;
f.write(st[1],60);
i := GetTickCount - i;

i zawsze i miałem < 10

Delphi7 ent, dysk Segate Baracuda SATA II

w sumie w pętli po 100 zapisów na przemian na 10 bajcie i 9999999 bajcie na każdym pliku

0

Dzięki za poświęcenie czasu. Nie wiem co mam o tym myśleć. Z jednej strony zapewne spróbuje jeszcze potestować i być może coś szczególnego w moim kodzie znajdę co rozwiąże problem. Z drugiej strony cóż to mogłoby być co powoduje zawieszenie się funkcji writefile na kilkadziesiąt sekund? Nie mam pojęcia. Rzecz tez w tym, że testując zapis i odczyt do/z pliku dostaję czasem ten problem zazwyczaj tylko w jednym miejscu kodu co mnie zastanawia. Choć kiedy próbuje wykonywać ten "wycięty" z klasy kod który jako ostatni podałem tez choć rzadziej zdarzają mi się te "przestoje" na funkcji writefile. Testowałem to na dwóch kompach.

0

może dasz skompilowany program do potestowania

0

jeszcze mi się nasunęło - masz antywira włączonego :>

0

Tak, używam antywira, próbowałem go wyłączać ale bez rezultatu.
Wydaje się, że znalazłem rozwiązanie mojego problemu choć cały czas testuję i juz nie mam jak na razie tych przestojów. Nie wspomniałem- bo nie sądziłem, że może mieć to jakiekolwiek znaczenie- że pliki, których używam mają rozszerzenie dt. Okazało się, że to rozszerzenie jest na liście rozszerzeń microsoftu plików monitorowanych jeśli jest w systemie włączone monitorowanie danego dysku. Na ogół po zainstalowaniu windows wyłączam monitorowanie na wszystkich dyskach poza systemowym, tym razem jakoś o tym zapomniałem i monitorowanie miałem włączone. Wydaje się że te przestoje podczas wykonywania funkcji windows.writefile były spowodowane właśnie "podłączaniem się" procedur monitorujących, które sobie coś tam w tym momencie robiły/ zapisywały. Teraz wyłączyłem monitorowanie na tym dysku i od kilku godzin nie zaobserwowałem przestoju podczas działania windows.writefile. Mam nadzieję, ze to rzeczywiście ten powód i że już będzie ok:-)

Serdecznie dziękuję wszystkim za zainteresowanie moim problemem, poświęcony czas i próby pomocy.

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