5

ネットワーク上の他の場所にあるディスクファイル(100Mbイーサネット)から定期的に読み取るDelphi2006で記述されたアプリがあります。メインスレッドのアイドル状態のハンドラーから読み取りが行われるため、ネットワークを介した読み取りに非常に長い時間(20秒など)がかかり、アプリがフリーズする場合があります。

OK、読み取り操作を独自のスレッドに入れることはできますが、ファイル操作のタイムアウトを指定して、あきらめて他のことをしたり、レポートしたりできるかどうかを知りたいのです。読み取りが20秒より少し早く引っ掛かったという事実。

function ReadWithTimeout (var Buffer     ;
                              N       : integer ; 
                              Timeout : integer) : boolean ;

begin
Result := false
try
    SetReadTimeout (Timeout) ;          //  <==========================???
    FileStream.Read (Buffer, N) ;
    Result := true ;
except 
    ... 
    end ;
end ;
4

2 に答える 2

9

を呼び出すときにフラグを含めて、非同期アクセス用にファイルを開きます。を呼び出すときにレコードを渡します。読み取りがすぐに完了しない場合、関数は早期に戻ります。構造体に格納するイベントを呼び出すことにより、読み取りが完了するのを待つ時間を制御できます。待つこともできます。そうすれば、読み取りが完了するメッセージが到着するかのどちらか早い方ですぐに通知を受けることができるので、プログラムをハングさせる必要はまったくありません。メッセージの処理が終了したら、I / Oが完了したかどうかを再度確認するか、待機を再開するか、またはを呼び出してI/Oをあきらめることができます。File_Flag_OverlappedCreateFileTOverlappedReadFileWaitForSingleObjectTOverlappedMsgWaitForMultipleObjectsGetOverlappedResultCancelIo。これらすべての機能のドキュメントを注意深くお読みください。非同期I/Oは簡単ではありません。

于 2010-11-17T05:32:03.210 に答える
0

読み取り操作をスレッドに移動した後、読み取る前に timeGetTime によって返された値を格納できます。

isReading := true;
try
  startedAt := timeGetTime;
  FileStream.Read (Buffer, N);
  ...
finally
  isReading := false;
end;

時間がかかりすぎる場合は、アイドルハンドラーをチェックインします。

例えば:

function ticksElapsed( FromTicks, ToTicks : cardinal ) : cardinal;
begin
  if FromTicks < ToTicks
    then Result := ToTicks - FromTicks
    else Result := ( high(cardinal) - FromTicks ) + ToTicks; // There was a wraparound
end;

...

if isReading and ( ticksElapsed( startedAt, timeGetTime ) > 10 * 1000 ) // Taken too long? ~10s
then // Do something
于 2010-11-17T02:21:33.630 に答える