Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.058 c
15-1346860652
Дмитрий С
2012-09-05 19:57
2013.03.22
Generic и неGeneric типы одинаковые в памяти?


15-1339705802
Юрий
2012-06-15 00:30
2013.03.22
С днем рождения ! 15 июня 2012 пятница


15-1337965875
alexdn
2012-05-25 21:11
2013.03.22
Php


2-1345708838
Molchanov
2012-08-23 12:00
2013.03.22
Высокоскоростной обмен с аппаратурой


2-1330002674
Den
2012-02-23 17:11
2013.03.22
Вместо TWebBrowser использовать FireFox?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский