![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
потоки->логи
braza © (2012-11-01 09:39:00)Подскажите как организовать запись данных от нескольких потоков в файл, посредством другого потока без использования окон и сообщений
чтото типа - послал поток данные и не дожидаясь обработки работает дальше, а поток "логер" уже сам, "постепенно" пишет это все в файл и т.д.
Dmitriy (2012-11-02 14:52:00) [1]
> Это уже не одновременно. Это последовательно в конечном
> итоге. Так что не будет "одновременно"
ну вопрос то про "одновременно" (с.т.относ не примешиваем) произошедшие события.
в этом случае, для ожидающего их потока - система разложит события на последовательные в зависимости от порядка их указания в @Events
DVM (2012-11-02 10:00:00) [2]
> Dmitriy (02.11.12 09:25) [20]
>
> > а если одновременно ?
>
>
> а если одновременно - то сначала первый сработавший индекс,
> при повторном обращении - следующий.
>
>
Это уже не одновременно. Это последовательно в конечном итоге. Так что не будет "одновременно"
Dmitriy (2012-11-02 09:26:00) [3]
> сначала первый сработавший индекс
то есть минимальный сработавший индекс - если сработали 5, 1, 3
то вернет сначала 1, потом 3, потом 5
но это implementation details - на них полагаться нельзя.
Dmitriy (2012-11-02 09:25:00) [4]
> а если одновременно ?
а если одновременно - то сначала первый сработавший индекс, при повторном обращении - следующий.
braza (2012-11-01 18:24:00) [5]2й вар всетаки предпочтительней
это она типа индекс итема массива сработавшего хэндла возвращает? а если одновременно ?
DVM (2012-11-01 17:22:00) [6]
> а есть ли какая метода, вот ждет поток события, а надо еще
> и время отслеживать, ну типа поминутно например
> это как сделать чтобы ожидая например через 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;
Dmitriy (2012-11-01 17:17:00) [7]
> я пря чувствую
научи сканированию через монитор!!!
braza (2012-11-01 17:10:00) [8]
> Dmitriy (01.11.12 16:54) [15]
я пря чувствую как у тебя все чешется чтоб выложить готовый код...
Dmitriy (2012-11-01 16:54:00) [9]
> Я не знаю какой там у тебя список, если ты зуб даешь, что
> добавление данных в твой список атомарная операция, то флаг
> тебе в руки. Но я бы не был так уверен.
достаточно просто делается, кстати.
единственная сложность - обойти сравнение голова/хвост
я - обошел.
braza (2012-11-01 16:47:00) [10]
> DVM © (01.11.12 15:03) [13]
я про него и думал
типа он как свойство пишущего потока
в него добавляют другие потоки, оповещают (хз как)
вооот...
а есть ли какая метода, вот ждет поток события, а надо еще и время отслеживать, ну типа поминутно например
это как сделать чтобы ожидая например через WaitForXXXObjects он различал что это "таймер" или поток лог добавил?
DVM (2012-11-01 15:03:00) [11]
> braza (01.11.12 14:32) [10]
Такую очередь как ты хочешь в принципе тоже можно сделать. TThreadList он на более широкое применение рассчитан все же, а не на только чтение с начала а добавление в конец.
DVM (2012-11-01 14:59:00) [12]
> braza (01.11.12 14:32) [10]
> это невозможно :) в список добавляется указатель на полностью
> сформированые данные
Я не знаю какой там у тебя список, если ты зуб даешь, что добавление данных в твой список атомарная операция, то флаг тебе в руки. Но я бы не был так уверен. В TThreadList тоже указатели по сути добавляются, однако ж там нет возможности считать значение без блокировки.
Андреевич (2012-11-01 14:39:00) [13]
> А смысл такого логгирования? Если логгер не успевает сбрасывать
> лог на диск, то рано или поздно кончится оперативная память,
> так какая разница, блокирует логгер вызывающий поток или
> нет на время записи.
такое полезно если нагрузка бывает большая переодически. я такой подход применяю при сохранении скриншота в игре, если игра запущена с флешки, то запись картинки в папку игры занимает очень даже ощутимо по времени. А так игрок понажимал prtscr и поток "неспешно" по очереди все картинки сохранит
braza (2012-11-01 14:32:00) [14]
> DVM © (01.11.12 14:26) [9]
это невозможно :) в список добавляется указатель на полностью сформированые данные
DVM (2012-11-01 14:26:00) [15]
> braza (01.11.12 14:25) [8]
> а зачем блочить при чтении то ?
Чтобы не считать не до конца добавленную запись
braza (2012-11-01 14:25:00) [16]
> Из него нельзя читать и писать сразу на диск, т.к. тогда
> его придется на время чтения блокировать,
а зачем блочить при чтении то ? добавляеца в конец а читаеца с начала,как сохранил удалил
DVM (2012-11-01 14:15:00) [17]
> braza (01.11.12 13:21) [6]
> так ужеш есть
Тот который потокозащищенный? Из него нельзя читать и писать сразу на диск, т.к. тогда его придется на время чтения блокировать, а т.к. запись на диск занимает в этой цепочке самое большое время то и в список этот добавить будет ничего нельзя пока он заблокирован. Поэтому у потока непосредственно пишущего на диск и должен быть свой внутренний (уже не потокозащищенный) список или очередь в который он копирует данные и потом пишет их не торопясь, а как записал засыпает или если к тому времени событие было взведено опять то опять копирует данные из глобального списка.
Есть еще более скоростной вариант, который исключает ожидание потоками друг друга даже на добавлении данных в общий глобальный список. Каждый поток регистрирует себя каким либо образом и для него создается свой потокозащищенный список в который он может писать не ожидая блокировки со стороны других потоков-писателей. Поток же пишущий лог обращается к этим спискам поочередно или еще как (механизм уведомлений может быть разный) и забирает сообщения. Но тогда мы терям хронологию добавления сообщений в лог между разными потоками.
Еще вариант - каждый поток пишет в свой файл.
braza (2012-11-01 13:21:00) [18]
> быстренько копирует строки в свой внутренний спис
так ужеш есть
> свой потокозащищенный список
?
DVM (2012-11-01 11:49:00) [19]
> braza (01.11.12 10:32) [3]
> Log4d фтопку
> нужна просто мысль как законтачить потоки друг с другом,
> иначе сплошная деградация :(
Ты хоть пытался вникнуть в написанное мной выше?
Чтобы потоки логгировали в одно место, требуется синхронизация по-любому. Т.е как минимум крит секция. Она есть в Log4d. Сам логгер ничего не пишет никуда, он лишь передает данные писателям (аппендерам), которые вольны распоряжаться полученными данными как заблагорассудится. Момент передачи данных аппендеру должен быть синхронизован, а дальше аппендер в зависимости от своего типа может и в OutputDebugString выводить и по сети передавать и в файл писать и в базу и в системный EventLog и в SysLog и т.д. и т.п куда только захочешь. Как сделаешь аппендер так и будет.
По поводу как законтачить - все очень просто.
Аппендер (писатель) имеет свой потокозащищенный список в который добавляются максимально быстро новые сообщения. Список на время добавления лочится. Также он имеет отдельный поток, который в большую часть времени спит на WaitForXXXObjects ожидая взведения события изменения этого самого списка. По событию поток просыпается и быстренько копирует строки в свой внутренний список, сбрасывает событие и пишет данные куда угодно и потом опять засыпает. И так по кругу. Таким образом запись на диск не тормозит поток который генерит сообщения для логгирования.
Rouse_ (2012-11-01 11:10:00) [20]OutputDebugString() + DebugView снаружи, логируй сколько влезет...