Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.06.02;
Скачать: [xml.tar.bz2];

Вниз

потоки->логи   Найти похожие ветки 

 
braza   (2012-11-01 09:39) [0]

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


 
MBo ©   (2012-11-01 09:44) [1]

Вот тут Log4d советуют:
http://delphimaster.net/view/15-1351711327/


 
DVM ©   (2012-11-01 10:04) [2]


> а поток "логер" уже сам, "постепенно" пишет это все в файл
> и т.д.

А смысл такого логгирования? Если логгер не успевает сбрасывать лог на диск, то рано или поздно кончится оперативная память, так какая разница, блокирует логгер вызывающий поток или нет на время записи.

По поводу Log4d ситуация такая. Сама передача данных логгеру защищена крит секцией, но пока все Appender-ы не запишут свои данные, логгер блокирован. Но никто не мешает написать свой аппендер по аналогии (что идеологией Log4 приветствуется) с буфером, который будет сбрасывать данные в фоне.


 
braza   (2012-11-01 10:32) [3]

Log4d фтопку
нужна просто мысль как законтачить потоки друг с другом, иначе сплошная деградация :(

> DVM ©   (01.11.12 10:04) [2]

смысл, что пока поток будет висеть в ожидании записи предупреждения он пропустит критическую ошибку
а память не критична ибо события не каждую милисекунду случаются и пишутся туда не басни Крылова, а вот диск занят кокраз большую часть времени


 
Rouse_ ©   (2012-11-01 11:10) [4]

OutputDebugString() + DebugView снаружи, логируй сколько влезет...


 
DVM ©   (2012-11-01 11:49) [5]


> braza   (01.11.12 10:32) [3]


> Log4d фтопку
> нужна просто мысль как законтачить потоки друг с другом,
>  иначе сплошная деградация :(

Ты хоть пытался вникнуть в написанное мной выше?
Чтобы потоки логгировали в одно место, требуется синхронизация по-любому. Т.е как минимум крит секция. Она есть в Log4d. Сам логгер ничего не пишет никуда, он лишь передает данные писателям (аппендерам), которые вольны распоряжаться полученными данными как заблагорассудится. Момент передачи данных аппендеру должен быть синхронизован, а дальше аппендер в зависимости от своего типа может и в OutputDebugString выводить и по сети передавать и в файл писать и в базу и в системный EventLog и в SysLog и т.д. и т.п куда только захочешь. Как сделаешь аппендер так и будет.

По поводу как законтачить - все очень просто.
Аппендер (писатель) имеет свой потокозащищенный список в который добавляются максимально быстро новые сообщения. Список на время добавления лочится. Также он имеет отдельный поток, который в большую часть времени спит на WaitForXXXObjects ожидая взведения события изменения этого самого списка. По событию поток просыпается и быстренько копирует строки в свой внутренний список, сбрасывает событие и пишет данные куда угодно и потом опять засыпает. И так по кругу. Таким образом запись на диск не тормозит поток который генерит сообщения для логгирования.


 
braza   (2012-11-01 13:21) [6]


> быстренько копирует строки в свой внутренний спис

так ужеш есть

> свой потокозащищенный список

?


 
DVM ©   (2012-11-01 14:15) [7]


> braza   (01.11.12 13:21) [6]


> так ужеш есть

Тот который потокозащищенный? Из него нельзя читать и писать сразу на диск, т.к. тогда его придется на время чтения блокировать, а т.к. запись на диск занимает в этой цепочке самое большое время то и в список этот добавить будет ничего нельзя пока он заблокирован. Поэтому у потока непосредственно пишущего на диск и должен быть свой внутренний (уже не потокозащищенный) список или очередь в который он копирует данные и потом пишет их не торопясь, а как записал засыпает или если к тому времени событие было взведено опять то опять копирует данные из глобального списка.

Есть еще более скоростной вариант, который исключает ожидание потоками друг друга даже на добавлении данных в общий глобальный список. Каждый поток регистрирует себя каким либо образом и для него создается свой потокозащищенный список в который он может писать не ожидая блокировки со стороны других потоков-писателей. Поток же пишущий лог обращается к этим спискам поочередно или еще как (механизм уведомлений может быть разный) и забирает сообщения. Но тогда мы терям хронологию добавления сообщений в лог между разными потоками.

Еще вариант - каждый поток пишет в свой файл.


 
braza   (2012-11-01 14:25) [8]


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

а зачем блочить при чтении то ? добавляеца в конец а читаеца с начала,как сохранил удалил


 
DVM ©   (2012-11-01 14:26) [9]


> braza   (01.11.12 14:25) [8]


> а зачем блочить при чтении то ?

Чтобы не считать не до конца добавленную запись


 
braza   (2012-11-01 14:32) [10]


> DVM ©   (01.11.12 14:26) [9]

это невозможно :) в список добавляется указатель на полностью сформированые данные


 
Андреевич   (2012-11-01 14:39) [11]


> А смысл такого логгирования? Если логгер не успевает сбрасывать
> лог на диск, то рано или поздно кончится оперативная память,
>  так какая разница, блокирует логгер вызывающий поток или
> нет на время записи.

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


 
DVM ©   (2012-11-01 14:59) [12]


> braza   (01.11.12 14:32) [10]


> это невозможно :) в список добавляется указатель на полностью
> сформированые данные

Я не знаю какой там у тебя список, если ты зуб даешь, что добавление данных в твой список атомарная операция, то флаг тебе в руки. Но я бы не был так уверен. В TThreadList тоже указатели по сути добавляются, однако ж там нет возможности считать значение без блокировки.


 
DVM ©   (2012-11-01 15:03) [13]


> braza   (01.11.12 14:32) [10]

Такую очередь как ты хочешь в принципе тоже можно сделать. TThreadList он на более широкое применение рассчитан все же, а не на только чтение с начала а добавление в конец.


 
braza   (2012-11-01 16:47) [14]


> DVM ©   (01.11.12 15:03) [13]

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


 
Dmitriy   (2012-11-01 16:54) [15]


> Я не знаю какой там у тебя список, если ты зуб даешь, что
> добавление данных в твой список атомарная операция, то флаг
> тебе в руки. Но я бы не был так уверен.


достаточно просто делается, кстати.

единственная сложность - обойти сравнение голова/хвост
я - обошел.


 
braza   (2012-11-01 17:10) [16]


> Dmitriy   (01.11.12 16:54) [15]

я пря чувствую как у тебя все чешется чтоб выложить готовый код...


 
Dmitriy   (2012-11-01 17:17) [17]


> я пря чувствую


научи сканированию через монитор!!!


 
DVM ©   (2012-11-01 17:22) [18]


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

Даже 2.

1) Последний параметр в WaitForXXXObjects + WAIT_TIMEOUT
2) SetWaitableTimer


     SetWaitableTimer(FTimer, TLargeInteger(FileTime), 0, nil, nil, FALSE);
     Events[0] := FTimer;
     Events[1] := FEventHandle;
     WaitResult := WaitForMultipleObjects(2, @Events[0], False, INFINITE);
     case WaitResult of
       WAIT_OBJECT_0:
         begin
           // сработал таймер
         end;
       WAIT_OBJECT_0 + 1:
         begin
           // сработало событие
         end;
       WAIT_FAILED:
         // Ошибка
         RaiseLastOSError;
     end;


 
braza   (2012-11-01 18:24) [19]

2й вар всетаки предпочтительней
это она типа индекс итема массива сработавшего хэндла возвращает? а если одновременно ?


 
Dmitriy   (2012-11-02 09:25) [20]


>  а если одновременно ?


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


 
Dmitriy   (2012-11-02 09:26) [21]


> сначала первый сработавший индекс


то есть минимальный сработавший индекс - если сработали 5, 1, 3
то вернет сначала 1, потом 3, потом 5
но это implementation details - на них полагаться нельзя.


 
DVM ©   (2012-11-02 10:00) [22]


> Dmitriy   (02.11.12 09:25) [20]
>
> >  а если одновременно ?
>
>
> а если одновременно - то сначала первый сработавший индекс,
>  при повторном обращении - следующий.
>
>

Это уже не одновременно. Это последовательно в конечном итоге. Так что не будет "одновременно"


 
Dmitriy   (2012-11-02 14:52) [23]


> Это уже не одновременно. Это последовательно в конечном
> итоге. Так что не будет "одновременно"


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



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

Форум: "Начинающим";
Текущий архив: 2013.06.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.005 c
2-1351922003
alexdn
2012-11-03 09:53
2013.06.02
Расширение формы


15-1359156796
Дмитрий С
2013-01-26 03:33
2013.06.02
как передается array of const?


15-1359384923
Error0xDEADBEEF
2013-01-28 18:55
2013.06.02
Пересесть с Delphi на Java/Android


15-1358877111
Дмитрий С
2013-01-22 21:51
2013.06.02
Почтовый ретранслятор.


15-1358177509
ES
2013-01-14 19:31
2013.06.02
Работа с внешним консольным приложением





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский