Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];
ВнизЗапись в файл из нескольких потоков Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.077 c