Запис в файл з декількох потоків

Запис в файл з декількох потоків

Доброго вам дня,
Може хто небудь може підказати яким чином організувати запис в фаил з різних потоків. Ідею знайшов таку створювати потік який буде робити фактичну запис а всі інші потоки будуть йому посилати PostMessage, але незнаю як це реалізувати, може хто-небудь може допомогти? Як це зробити, може хто знає більше правельно рішення?

Якщо потоки можуть перебувати в стані очікування, то досить використовувати критичну секцію

Як взагалі можна написати багатопоточний додатки, не знаючи, як потоку послати PostMessage?

> А всі інші потоки будуть йому посилати PostMessage
нормальна ідея, имхо, найпростіша (немає потреби ні в яких хитрощах). тільки не PostMessage, а PostThreadMessage.

> Може хто-небудь може допомогти?
загугли. і почни щось робити. питай конкретно, щоб було в чому допомагати. а то "в загальному" звучить як "зробіть за мене".

> Як взагалі можна написати багатопоточний додатки
хреново. взагалі найчастіше стикаюся з тим, що їх "ліплять" в код просто так "бо круто".

А потім дивишся в диспетчері завдань і думаєш ну навіщо такий простий програмою 50 потоків?

Повертаючись до даної задачі - а хто буде стежити за порядком запису в один файл з декількох потоків?

черговість буде дотримана "автоматом", по черзі повідомлень. перший прийшов - перший записався.

І де при цьому гарантія, що дані будуть записані в правильній послідовності?

що таке чергу знаєш? ну це наприклад патрони з автомата вилітають в порядку укладання в ріжок.
і де там гарантія правильної послідовності?
критерії "правильності" озвуч. якщо для тебе вона - десятий прийшов, але у нього "блат", значить першим повинен піти, то очевидно чергу тобі не підходить бо "неправильна".


> Критерії "правильності" озвуч

Тільки один - цілісність інформації. Якщо потоки почнуть абияк писати (дописувати) дані в файл, що тоді станеться? Навіть якщо вони в чергу вишикуються? Тут у нас не стек ЛІФО, яким є автоматний ріжок.


> Який сенс міркувати про деталі завдання

Про завдання вже все давно забули :)

Всім величезне спасибі за відповіді,
я не втік, буду сьогодні намагатися пробувати зробити все


# XA0; Захищений зв'язний список для роботи з чергою
# XA0; в багатопотоковому режимі (перший увійшов-перший вийшов)

uses
Windows,
SyncObjs,
SysUtils;

type
PItemList = ^ TItemList;
TItemList = record
# XA0; Prev, Next: PItemList;
# XA0; Data: # XA0; # XA0; # XA0; PChar;
end;

TPushPop = class (TObject)
private
# XA0; FCS: # XA0; # XA0; # XA0; # XA0; TCriticalSection;
# XA0; FRootItem: # XA0; PItemList;
# XA0; FLastItem: # XA0; PItemList;
# XA0; FItemsCount: integer;
# XA0; FWaitEvent: # XA0; THandle;
# XA0; procedure Lock;
# XA0; procedure Unlock;
# XA0; procedure DeleteItem0; inline;
# XA0; function GetCount: integer;
public
# XA0; constructor Create;
# XA0; destructor Destroy; override;
# XA0; procedure Push (const s: string);
# XA0; procedure PopAllToFile (const FileName: string);
# XA0; procedure PushFromFile (const FileName: string);
# XA0; function Exists (const Str: string): boolean;
# XA0; function Pop: string;
# XA0; function Peek: string;
# XA0; procedure Clear; inline;
# XA0; procedure WaitForItem;
# XA0; property Count: integer Read GetCount;
end;

const
FileDelim = # 1;

function ExtractFileFromConcate (const s: string): string; inline;
function ExtractAddInfoFromConcate (const s: string): string; inline;

constructor TPushPop.Create;
begin
inherited;
New (FRootItem);
New (FLastItem);

FRootItem.Prev: = nil;
FRootItem.Next: = FLastItem;
FRootItem.Data: = nil;
FLastItem.Prev: = FRootItem;
FLastItem.Data: = nil;
FLastItem.Next: = nil;

FCS: = TCriticalSection.Create;
FWaitEvent: = CreateEvent (nil, True, False, nil);
end;

destructor TPushPop.Destroy;
begin
Clear;
Dispose (FRootItem);
Dispose (FLastItem);
FreeAndNil (FCS);
CloseHandle (FWaitEvent);
inherited;
end;

function TPushPop.Exists (const Str: string): boolean;
var
CurrItem: PItemList;
begin
Lock;
try
# XA0; CurrItem: = FRootItem;
# XA0; Result: = False;
# XA0; while (CurrItem <> FLastItem) do
# XA0; begin
# XA0; if ExtractFileFromConcate (string (CurrItem.Data)) = Str then
# XA0; # XA0; Exit (True);
# XA0; CurrItem: = CurrItem.Next;
# XA0; end;
finally
# XA0; Unlock;
end;
end;

procedure TPushPop.Lock;
begin
FCS.Enter;
end;

procedure TPushPop.Unlock;
begin
FCS.Leave;
end;

procedure TPushPop.WaitForItem;
begin
WaitForSingleObject (FWaitEvent, INFINITE);
end;

procedure TPushPop.DeleteItem0;
var
p: PItemList;
begin
if FItemsCount = 0 then
# XA0; Exit;
p: = FRootItem.Next;

p.Prev.Next: = p.Next;
p.Next.Prev: = p.Prev;

function TPushPop.Peek: string;
var
Len: integer;
begin
Lock;
try
# XA0; Len: = StrLen (FRootItem.Next.Data);
# XA0; SetLength (Result, Len);
# XA0; move (FRootItem.Next.Data ^, Result [1], Len * SizeOf (char));
finally
# XA0; Unlock;
end;
end;

function TPushPop.Pop: string;
var
Len: integer;
begin
Lock;
try
# XA0; if Count = 0 then
# XA0; raise Exception.Create ( "UnderFlow in TPushPop.Pop!");
# XA0; Len: = StrLen (PWideChar (FRootItem.Next.Data));
# XA0; SetLength (Result, Len);
# XA0; if Len> 0 then
# XA0; move (FRootItem.Next.Data ^, Result [1], Len * SizeOf (char));
# XA0; FreeMem (FRootItem.Next.Data);
# XA0; DeleteItem0;
# XA0; if Count = 0 then
# XA0; ResetEvent (FWaitEvent);
finally
# XA0; Unlock;
end;
end;

procedure TPushPop.Push (const s: string);
var
p: PItemList;
TempChar: PChar;
begin
TempChar: = AllocMem ((Length (s) + 1) * SizeOf (char));
if Length (s)> 0 then
# XA0; move (s [1], TempChar ^, Length (s) * SizeOf (char));
Lock;
try
# XA0; New (p);
# XA0; p.Data: = TempChar;

# XA0; p.Prev: = FLastItem.Prev;
# XA0; p.Next: = FLastItem;
# XA0; FLastItem.Prev.Next: = p;
# XA0; FLastItem.Prev: = p;

# XA0; Inc (FItemsCount);
# XA0; SetEvent (FWaitEvent);
finally
# XA0; Unlock;
end;
end;

function TPushPop.GetCount: integer;
begin
if Assigned (FCS) then
begin
# XA0; Lock;
# XA0; try
# XA0; Result: = FItemsCount;
# XA0; finally
# XA0; Unlock;
# XA0; end;
end
else
# XA0; Result: = 0;
end;

procedure TPushPop.Clear;
begin
while Count <> 0 do
# XA0; Pop;
end;

procedure TPushPop.PopAllToFile (const FileName: string);
var
F: TextFile;
begin
if Count = 0 then
# XA0; Exit;
AssignFile (F, FileName);
try
# XA0; Rewrite (F);
except
# XA0; Exit;
end;
try
# XA0; while Count <> 0 do
# XA0; WriteLn (F, Pop);
finally
# XA0; CloseFile (F);
end;
end;

procedure TPushPop.PushFromFile (const FileName: string);
var
F: TextFile;
s: string;
begin
if not FileExists (FileName) then
# XA0; Exit;
AssignFile (F, FileName);
try
# XA0; Reset (F);
except
# XA0; Exit;
end;
try
# XA0; while not Eof (F) do
# XA0; begin
# XA0; ReadLn (F, s);
# XA0; Push (s);
# XA0; end;
finally
# XA0; CloseFile (F);
end;
DeleteFile (FileName);
end;

Як використовувати. З потрібних потоків робиш Push. З одного робиш Pop. Як варіант - періодично "смикати" PopAllToFile - клас сам збереже своє # XA0; вміст в файл.


> Що таке чергу знаєш? ну це наприклад патрони з автомата
> Вилітають в порядку укладання в ріжок.
> І де там гарантія правильної послідовності?

До речі, послідовності таки є. Вони не статутні, чисто індивідуальні. Але є. Наприклад, кожен третій - трасер. Або останні 5 - трассери.

> Наприклад, кожен третій - трасер. Або останні 5 - трассери.
це тип події (пострілу) в послідовності, а не вона сама. тут мова саме про порядок. тобто типу ти укладав в ріжок трассери через два, тобто чекаєш, що буде кожен третій, а воно раптом взяло і неправильно. спочатку все трасери, а після звичайні, або навпаки, або не кожен третій, а в середині трійки. Ну як то так. (А у тебе виходить, що якщо наприклад 3-й і 6-й, місцями поміняються то це як би правильно, хоча і неймовірно)
саме і хотілося з'ясувати критерії щоб зрозуміти, що він вважає неправильним в "перший послали, перший записався, і т.д."

Пам'ять: 0.78 MB
Час: 0.209 c