Текущий архив: 2007.10.21;
Скачать: CL | DM;
ВнизМежпотоковое взаимодействие: есть поток, который при Найти похожие ветки
← →
AlexEgorov (2007-04-24 09:41) [0]поступленнии данных создаёт другой поток для их обработки и продолжает ждать новые данные. Как из второго потока вернуть обработанные данные в первый поток в сервисе? Если работа идёт в приложении, то Sinchronyze - и никаких проблем, а в сервисе это не прокатывает, наверное из-за того, что нет главной формы, в контексе которой работает код в Sinchronyze. Что можно сделать в сервисе?
← →
MBo © (2007-04-24 09:46) [1]второй поток кладет данные в некий буфер и выставляет объект синхронизации, например, Event, а первый поток, дождавшись срабатывания, забирает данные
← →
Сергей М. © (2007-04-24 09:49) [2]Mожно также воспользоваться PostThreadMessage, если взаимодействие с раб.столом по каким-то причинам нежелательно. Иначе - SendMessage
← →
AlexEgorov (2007-04-24 09:58) [3]Сейчас у меня сделано так - после обработки данных второй поток перебирает список потоков поступающих данных (на самом деле их несколько), и устанавливает в нём Event, предварительно положив обработанные данные в некий буфер, как и предложил MBo.
Всё работает прекрасно, я не смог выловить каких-либо багов, но у клиента этот механизм дал сбой:
в потоке обработки данных есть критическая секция, чтобы стазу несколько потоков не положили систему, так вот похоже в какой-то момент эта сейция не освобождается и всё останавливается, т.к. все новые потоки обработки данных ждут освобождения секции, которая залочена :(
← →
Reindeer Moss Eater © (2007-04-24 10:02) [4]так вот похоже в какой-то момент эта сейция не освобождается и всё останавливается, т.к. все новые потоки обработки данных ждут освобождения секции, которая залочена :(
Наверное у тебя есть ошибка в программе
← →
Сергей М. © (2007-04-24 10:04) [5]
> AlexEgorov (24.04.07 09:58) [3]
Я так понял, что у тебя один обрабатывающий поток на несколько транспортных ?
Странная, однако, затея - "семеро с ложкой, один с сошкой")
← →
AlexEgorov (2007-04-24 10:08) [6]Я хотел сначала на каждый станспортный делать обрабатывающий, но в этом случае спулер входит в ступор :( - я мониторю входящие задания печати, и транспортные потоки, это потоки мониторинга принтеров. А обрабатывающий поток выдёргивает и парсит эти задания.
← →
MBo © (2007-04-24 10:11) [7]может, воспользоваться TMultiReadExclusiveWriteSynchronizer?
← →
AlexEgorov (2007-04-24 10:13) [8]А в каком из потоков? Мне же как-раз множественное чтение для нескольких обрабатывающих потоков ненужно, т.к. спулер вешается.
← →
Сергей М. © (2007-04-24 10:15) [9]
> спулер входит в ступор
Это как ?
← →
AlexEgorov (2007-04-24 10:17) [10]> Это как ?
Начинает сильно тормозить - рассматривается ситуация, когда принтеров в системе более 50-ти и задания печати поступают довольно часто
← →
Сергей М. © (2007-04-24 10:18) [11]Какой поток у тебя вызывает EnumJobs, а какой Get/Set/AddJob ?
← →
AlexEgorov (2007-04-24 10:21) [12]Я обрабатываю все задания печати через FindFirst/NextPrinterChangeNotification в транспортном потоке, там же поступившее задание ставится в паузу и создаётся обрабатывающий поток, котоый парсит новое задание печати и возвращает результат в транспортный поток, после этого транспортный поток делает заданию Resume, а после того, как задание напечатано, сохраняет данные о задании и ждёт следующие
← →
Сергей М. © (2007-04-24 10:33) [13]Pausing a printer suspends scheduling of all print jobs for that printer, except for the one print job that may be currently printing.
Что на это скажешь ?
← →
AlexEgorov (2007-04-24 10:34) [14]Нет, паузится не принтер, а задание печати, которое нужно парсить
← →
Сергей М. © (2007-04-24 10:35) [15]Каким образом ?
← →
AlexEgorov (2007-04-24 10:38) [16]> Каким образом ?
Приходит сообщение о новом задании печати в очереди и я ставлю задание в паузу SetJob(...). Потом дожитаюсь собития, что задание полностью встало в очередь (спулинг закончился) после этого вызываю обрабатывающий поток и продолжаю мониторить задания печати
← →
Сергей М. © (2007-04-24 10:46) [17]А на каком этапе спулер начинает "тормозить" ?
← →
AlexEgorov (2007-04-24 10:52) [18]Если каждый транспортный поток создаст свой обрабатывающий, то все они ломанутся на чтение содержимого заданий печати - вот тут и возникает торможение, особенно если задание печати здоровые (а они для плоттеров от сотни мегабайт идут). Для этого и сделан один обрабатывающий поток.
← →
Сергей М. © (2007-04-24 10:54) [19]
> то все они ломанутся на чтение содержимого заданий печати
Так ты защити процедуру чтения крит.секцией - и всех делов ..
← →
Сергей М. © (2007-04-24 10:57) [20]Уж раз чтение осуществляется в обрабатывающем потоке, то это уже совсем не обрабатывающий поток - ты там замесил и транспортные и обрабатывающие функции в одну кучу.
Либо перенеси чтение в трансп.поток (тогда защита крит.секцией не нужна), либо, как уже сказано, защищай чтение со стороны нескольких обр.потоков крит.секцией.
← →
AlexEgorov (2007-04-24 11:02) [21]> Так ты защити процедуру чтения крит.секцией - и всех делов ..
Так я и сделал:
EnterCriticalSection(csJobsThread);
try
ParseJob(Job)
finally
LeaveCriticalSection(csJobsThread);
end;
Но похоже, по какой-то причине в определённый момент не срабатывает LeaveCriticalSection и обрабатывающие потоки начинают копиться :(
> Либо перенеси чтение в трансп.поток
Т.к. чтение операция небыстрая, то в момент чтения не обрабатываются новые задание печати, а когда очередь до них доходит, то они уже как правило напечатаны, т.к. небыли в паузу вовремя поставлены
← →
Сергей М. © (2007-04-24 11:11) [22]
> по какой-то причине в определённый момент не срабатывает
> LeaveCriticalSection
Такого быть не может ...
Покажи, что у тебя творится в теле ParseJob ..
← →
AlexEgorov (2007-04-24 11:42) [23]Там кода много с вызовом сопутствующих функций. В общем сейчас с логами версию пользователю отправлю, может что-то прояснится, если нет то вернусь к обсуждению, спасибо
← →
Сергей М. © (2007-04-24 11:46) [24]
> Там кода много с вызовом сопутствующих функций
А весь код и не нужен.
Интересует только фрагменты, где осуществляется чтение и запись данных задания.
← →
AlexEgorov (2007-04-24 12:01) [25]Сначала вызывается
OpenPrinterW(PWideChar(PrnName + ",Job " + IntToWideStr(JobId)), hPrn, nil);
потом читается всё задание функцией ReadPrinter с записью прочитанного в файл, параллельно с этим происходит парсинг, т.е. в процессе чтения. Там для разных типов заданий разные методы парсинга.
← →
AlexEgorov (2007-04-24 12:01) [26]Сначала вызывается
OpenPrinterW(PWideChar(PrnName + ",Job " + IntToWideStr(JobId)), hPrn, nil);
потом читается всё задание функцией ReadPrinter с записью прочитанного в файл, параллельно с этим происходит парсинг, т.е. в процессе чтения. Там для разных типов заданий разные методы парсинга.
← →
Сергей М. © (2007-04-24 12:05) [27]
> потом читается всё задание функцией ReadPrinter
Не понял ..
Почему не GetJob ?
← →
AlexEgorov (2007-04-24 12:55) [28]Потому что мне нужно просмотреть именно содержимое задания печати, т.к. в JOB_INFO_* не всегда нужная информация есть, например количество копий для заданий отправленных из Word или для заданий отравленный с Linux/Mac/Solaris, или для заданий отправленных через IPP. В общем много случаем, когда GetJob не может помочь
← →
Сергей М. © (2007-04-24 13:11) [29]
> много случаем, когда GetJob не может помочь
>
Ну хорошо, пусть с этой точки зрения ReadPrinter будет предпочтительней.
Но я о временной замене ReadPrinter на GetJob с целью установить "узкое" место в алгоритме ...
← →
AlexEgorov (2007-04-24 13:55) [30]Понятно, попробую парсинг вообще пока заменить пустыкой и пользователю отправить на тест, у меня-то всё работает на сервере с >100 принтеров и по несколько заданий в секунду... А у него и нагрузка меньше и принтеров меньше, а тем не менее возникает странная ситуация
Страницы: 1 вся ветка
Текущий архив: 2007.10.21;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.041 c