Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

Запись в файл из нескольких потоков   Найти похожие ветки 

 
sergeii01   (2012-02-01 17:01) [0]

Доброго времени суток,
Может кто нибудь может подсказать каким образом организовать запись в фаил из разных потоков. Идею нашёл такую создавать поток который будет делать фактическую запись а все остальные потоки будут ему посылать PostMessage, но незнаю как это реализовать, может ктонибудь может помочь? Как это сделать, может кто знает более правельное решение?

Спасибо


 
MBo ©   (2012-02-01 17:59) [1]

Если потоки могут находиться в состоянии ожидания, то достаточно использовать критическую секцию


 
Dimka Maslov ©   (2012-02-01 19:36) [2]

Как вообще можно написать многопоточное приложения, не зная, как потоку послать PostMessage?


 
sniknik ©   (2012-02-01 19:36) [3]

> а все остальные потоки будут ему посылать PostMessage
нормальная идея, имхо, самая простая (нет нужды ни в каких ухищрениях). только не PostMessage, а PostThreadMessage.

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


 
sniknik ©   (2012-02-01 19:41) [4]

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


 
Dimka Maslov ©   (2012-02-01 20:49) [5]


> sniknik ©   (01.02.12 19:41) [4]


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

Возвращаясь к данной задаче - а кто будет следить за порядком записи в один файл из нескольких потоков?


 
sniknik ©   (2012-02-01 21:07) [6]

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


 
Dimka Maslov ©   (2012-02-01 21:38) [7]

И где при этом гарантия, что данные будут записаны в правильной последовательности?


 
sniknik ©   (2012-02-01 23:10) [8]

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


 
Германн ©   (2012-02-02 01:04) [9]


> Dimka Maslov ©   (01.02.12 21:38) [7]

Какой смысл рассуждать о деталях задачи, которая не представлена. В наличии есть только вопрос про посылку сообщения из одного потока в другой.


 
Dimka Maslov ©   (2012-02-02 10:04) [10]


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


Только один - целостность информации. Если потоки начнут как попало писать (дописывать) данные в файл, что тогда произойдёт? Даже если они в очередь выстроятся? Тут у нас не стек ЛИФО, коим является автоматный рожок.


> Какой смысл рассуждать о деталях задачи


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


 
Anatoly Podgoretsky ©   (2012-02-02 10:59) [11]

А автор сбежал


 
sergeii01   (2012-02-02 11:24) [12]

Всем огромное спасибо за ответы,
я не сбежал, буду сегодня пытаться пробовать сделать всё

Спасибо


 
Дмитрий Белькевич   (2012-02-06 01:29) [13]

Есть такой замечательный модуль - uPushPop порылся, поискал, кто опубликовал - вроде бы panov. Брал здесь же на форуме, насколько я помню.
Публикую с небольшими улучшениями и минимумом частной обвзяки.


{
 Защищенный связный список для работы с очередью
 в многопоточном режиме(первый вошел-первый вышел)

}
unit uPushPop;

interface

uses
Windows,
SyncObjs,
SysUtils;

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

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

const
FileDelim = #1;

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

implementation

{ TPushPop }

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 ExtractFileFromConcate(const s: string): string;
begin
Result := Copy(s, 1, Pos(FileDelim, s) - 1);
end;

function ExtractAddInfoFromConcate(const s: string): string;
begin
Result := Copy(s, Pos(FileDelim, s) + 1, MaxInt);
end;

function TPushPop.Exists(const Str: string): boolean;
var
CurrItem: PItemList;
begin
Lock;
try
 CurrItem := FRootItem;
 Result := False;
 while (CurrItem <> FLastItem) do
 begin
  if ExtractFileFromConcate(string(CurrItem.Data)) = Str then
   Exit(True);
  CurrItem := CurrItem.Next;
 end;
finally
 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
 Exit;
p := FRootItem.Next;

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

Dispose(p);
Dec(FItemsCount);
end;

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

function TPushPop.Pop: string;
var
Len: integer;
begin
Lock;
try
 if Count = 0 then
  raise Exception.Create("UnderFlow in TPushPop.Pop!");
 Len := StrLen(PWideChar(FRootItem.Next.Data));
 SetLength(Result, Len);
 if Len > 0 then
  move(FRootItem.Next.Data^, Result[1], Len * SizeOf(char));
 FreeMem(FRootItem.Next.Data);
 DeleteItem0;
 if Count = 0 then
  ResetEvent(FWaitEvent);
finally
 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
 move(s[1], TempChar^, Length(s) * SizeOf(char));
Lock;
try
 New(p);
 p.Data := TempChar;

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

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

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

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

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

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

end.


Как пользовать. Из нужных потоков делаешь Push. Из одного делаешь Pop. Как вариант - периодически "дёргать" PopAllToFile - класс сам сохранит своё  содержимое в файл.


 
Дмитрий Белькевич   (2012-02-06 01:34) [14]

Да, Delphi 2010, в 7-ке скорее всего будет работать, слегка только поправить: Exit(True);


 
Германн ©   (2012-02-06 02:10) [15]


> порылся, поискал, кто опубликовал - вроде бы panov

Очень похоже, что это мог написать Саша Панов. Он когда-то работал над записью лога в многопоточном приложении и публиковал тут свои наработки по этой теме.


 
Ega23 ©   (2012-02-06 08:06) [16]


> что такое очередь знаешь? ну это например патроны из автомата
> вылетают в порядке укладки в рожок...
> и где там гарантия правильной последовательности?


Кстати, последовательности таки есть. Они не уставные, чисто индивидуальные. Но есть. Например, каждый третий - трассер. Или последние 5 - трассеры.


 
sniknik ©   (2012-02-06 10:30) [17]

> Например, каждый третий - трассер. Или последние 5 - трассеры.
это тип события (выстрела) в последовательности, а не она сама. тут речь именно о порядке... т.е. типа ты укладывал в рожок трассеры через два, т.е. ждешь, что будет каждый третий, а оно вдруг взяло и неправильно ... сначала все трасеры, а после обычные, или наоборот, или не каждый третий, а в середине тройки... ну как-то так. (а у тебя получается, что если к примеру 3-й и 6-й, местами поменяются то это как бы правильно, хотя и невероятно)
именно и хотелось выяснить критерии чтобы понять, что он считает неправильным в "первый послали, первый записался, и т.д."



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.153 c
2-1339501862
Scott Storch
2012-06-12 15:51
2013.03.22
PResStringRec -> string


15-1330893003
Юрий
2012-03-05 00:30
2013.03.22
С днем рождения ! 5 марта 2012 понедельник


2-1337494785
TStas
2012-05-20 10:19
2013.03.22
MethodName


2-1333239798
toropoff
2012-04-01 04:23
2013.03.22
чтение WMI


2-1336248923
rodionov-uv
2012-05-06 00:15
2013.03.22
Документ Word и Delphi