AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Datei im hintergrund in einen Puffer schreiben
Thema durchsuchen
Ansicht
Themen-Optionen

Datei im hintergrund in einen Puffer schreiben

Ein Thema von ThePirate · begonnen am 2. Apr 2013
Antwort Antwort
ThePirate

Registriert seit: 29. Mär 2013
1 Beiträge
 
Delphi 2010 Architect
 
#1

Datei im hintergrund in einen Puffer schreiben

  Alt 2. Apr 2013, 20:04
Ich habe ein Programm welches den CRC von Dateien berechnet nun wollte ich im Hintergrund, also währen der CRC aktualisiert wird, die Dateien in einen Puffer laden um den Prozess etwas zu beschleunigen aber wenn ich meinen Thread verwende hängt meistens mein Programm, der CRC ist falsch oder er stimmt. Leider finde ich den Fehler nicht.

Hier mein Thread code
Delphi-Quellcode:
unit MyBufferFillerThread;

interface

uses
  Windows, Classes, SyncObjs, Generics.Collections;

const
  cMyBufferFillerThreadDefaultBufferSize = $400000;//1 shl 22; // 4 MiB
  cMyBufferFillerThreadDefaultBlockSize = $8000; //1 shl 15; // 32 KiB

type
  TMyBufferFillerThread = class(TThread)
    private
      type
        TMyBlockItem = record
          Data : pointer;
          Size : integer;
          LastBlock : boolean;
        end;
        TMyBlockItemQueue = TQueue<TMyBlockItem>;


    private
      var
        FBlockSize : integer; // block size
        FBufferSize : integer; // buffer length, must be > FBlockSize
        FBuffer : Pointer; // buffer pointer
        FBlocksCount : integer;

        FStream : TStream; // stream to read from
        FOwnsStream : boolean; // owns stream

        FReadQueue : TMyBlockItemQueue; // ready to read data
        FWriteQueue : TMyBlockItemQueue; // free blocks

        FCrtSec : TCriticalSection;

        FPosition : int64;
        FSize : int64;
        FEndOfFile : boolean; // will be true if the last block was retrieved with Read


      procedure BlockLoaded (var Item: TMyBlockItem);
      procedure BlockRead (var Item: TMyBlockItem);
      function CanReadBlock: boolean;
      function CanWriteBlock: boolean;


    protected
      procedure Execute; override;
      procedure SetThreadParameters(const Stream: TStream; const OwnsStream: boolean; const BufferSize: integer; const BlockSize: integer);


    public
      class function CreateBufferFillerThread(const Stream: TStream; const OwnsStream: boolean = True; const BufferSize: integer = cMyBufferFillerThreadDefaultBufferSize; const BlockSize: integer = cMyBufferFillerThreadDefaultBlockSize): TMyBufferFillerThread;
      destructor Destroy; override;

      function Read(var Buffer): integer; // reads a block (FBlockSize) to your buffer, returns actual size like TStream

      property Position : int64 read FPosition;
      property Size : int64 read FSize;
      property EndOfFile : boolean read FEndOfFile;

  end;

implementation

{ TMyBufferFillerThread }

class function TMyBufferFillerThread.CreateBufferFillerThread(const Stream: TStream; const OwnsStream: boolean; const BufferSize: integer; const BlockSize: integer): TMyBufferFillerThread;
begin
  result:= TMyBufferFillerThread.Create(true);
  with result do
  begin
    FreeOnTerminate := false;
    FBuffer := nil;
    FCrtSec := TCriticalSection.Create;
    FReadQueue := TMyBlockItemQueue.Create;
    FWriteQueue := TMyBlockItemQueue.Create;
    SetThreadParameters(Stream, OwnsStream, BufferSize, BlockSize);
  end;
end;

procedure TMyBufferFillerThread.SetThreadParameters(const Stream: TStream; const OwnsStream: boolean; const BufferSize: integer; const BlockSize: integer);
var i: integer; itm: TMyBlockItem;
begin
  if FBuffer <> nil then
    FreeMemory(FBuffer);

  FBlockSize := BlockSize;
  FBufferSize := BufferSize div FBlockSize * FBlockSize + FBlockSize; // needs to be a multiple of BlockSize
  FBuffer := GetMemory(FBufferSize);
  FBlocksCount := FBufferSize div FBlockSize; // max blocks we can cache

  FStream := Stream;
  FOwnsStream := OwnsStream;

  FPosition := FStream.Position;
  FSize := FStream.Size;
  FEndOfFile := false;

  FReadQueue.Clear;
  FWriteQueue.Clear;

  for i := 0 to FBlocksCount - 1 do
  begin
    itm.Data := Pointer( integer(FBuffer) + (i * FBlockSize) );
    itm.Size := 0;
    itm.LastBlock := False;

    FWriteQueue.Enqueue(itm);
  end;

end;

destructor TMyBufferFillerThread.Destroy;
begin
  if FBuffer <> nil then
    FreeMemory(FBuffer);

  if FOwnsStream then
    FStream.Free;

  FCrtSec.Free;

  FReadQueue.Free;
  FWriteQueue.Free;

  inherited;
end;

procedure TMyBufferFillerThread.BlockLoaded(var Item: TMyBlockItem);
begin
  FCrtSec.Enter;
  FReadQueue.Enqueue(Item);
  FCrtSec.Leave;
end;

procedure TMyBufferFillerThread.BlockRead(var Item: TMyBlockItem);
begin
  FCrtSec.Enter;
  FWriteQueue.Enqueue(Item);
  FCrtSec.Leave;

  if Suspended then
    Suspended:= false;

end;

function TMyBufferFillerThread.CanReadBlock;
begin
  FCrtSec.Enter;
  result:= FReadQueue.Count > 0;
  FCrtSec.Leave;
end;

function TMyBufferFillerThread.CanWriteBlock;
begin
  FCrtSec.Enter;
  result:= FWriteQueue.Count > 0;
  FCrtSec.Leave;
end;

function TMyBufferFillerThread.Read(var Buffer): integer;
var itm: TMyBlockItem;
begin
  if FEndOfFile then // nothing left
  begin
    result:= 0;
    exit;
  end;

  while not CanReadBlock do
    Sleep(5);

  FCrtSec.Enter;
  itm := FReadQueue.Dequeue;
  FCrtSec.Leave;

  result := itm.Size;
  FEndOfFile:= itm.LastBlock;

  CopyMemory(@Buffer, itm.Data, result);

  BlockRead(itm);

  Inc(FPosition, itm.Size);
end;

procedure TMyBufferFillerThread.Execute;
var itm: TMyBlockItem; s, p: int64;
begin
  { Place thread code here }
  s:= FSize;
  p:= FPosition;
  while (p < s) and (not Terminated) do
  begin
    if (not CanWriteBlock) and (not Terminated) then
      Suspended:= true;

    if Terminated then
      exit;

    FCrtSec.Enter;
    itm:= FWriteQueue.Dequeue;
    FCrtSec.Leave;

    itm.Size := FStream.Read(itm.Data^, FBlockSize);

    Inc(p, itm.Size);

    itm.LastBlock := s = p;

    BlockLoaded(itm);
  end;
end;

end.
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz