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

Вниз

wait functions   Найти похожие ветки 

 
Polevi ©   (2006-02-01 12:09) [0]

несколько потоков ждут семафор
насколько возможно предсказать в каком порядке потоки проснуться при вызове ReleaseSemaphore ?
FIFO, LIFO или случайным образом ?

у меня есть пул потоков который обслуживает запросы клиентов
пул наращиваемый, алгоритм удаления потока следующий - он удаляется если ждет объекта более 1 минуты к примеру
я опасаюсь что данный алгоритм не будет работать если потоки будут получать управление в порядке вызова ими Wait ф-ии, в моем случае они будут получать управление по очереди даже если будет только один клиент

какие будут соображения, господа ?


 
Игорь Шевченко ©   (2006-02-01 12:29) [1]


> насколько возможно предсказать в каком порядке потоки проснуться
> при вызове ReleaseSemaphore ?


Насколько я знаю, FIFO


 
Leonid Troyanovsky ©   (2006-02-01 12:34) [2]


> Polevi ©   (01.02.06 12:09)  

> какие будут соображения, господа ?


У Соломона-Руссиновича оно подробно изложено, кое-что - у Таненбаума,
если мне не изменяет склероз.
Т.е., насколько я помню, для выборов из равноприоритетных потоков
используется витиеватый алгоритм, который, IMHO, не документирован.

--
Regards, LVT.


 
Digitman ©   (2006-02-01 12:41) [3]


> Polevi ©   (01.02.06 12:09)


А зачем ты уничтожаешь объект-трэд по тайм-ауту ?
Только лишь из-за экономии ресурсов ?
Ведь создание и старт трэда сродни пуску холодного автодвигателя !
Не проигрываешь ли ты в скорости реакции приложения на кл.запросы, пытаясь выиграть в ресурсах ?


 
Polevi ©   (2006-02-01 12:45) [4]

тест показал что FIFO, что очень жаль
в моем случае нужен LIFO


 
Polevi ©   (2006-02-01 12:50) [5]

>Digitman ©   (01.02.06 12:41) [3]
это все настраивается значениями таймаутов
доп поток создается при наличие в очереди запроса ожидающего больше X, уничтожается если ничего не делает больше Y


 
Игорь Шевченко ©   (2006-02-01 12:51) [6]


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


То есть, каждый поток вызывает WaitForSingleObject с таймаутом в минуту, после освобождения семафора они просыпаются все, и каждый решает, что именно он должен обслуживать запрос ? Или по WAIT_TIMEOUT они все удаляются ?


 
Polevi ©   (2006-02-01 13:21) [7]

например есть 3 потока и один клиент
пул потоков выглядит так - в порядке вызова Wait ф-ии
1
2
3
клиент поместил запрос в очередь и вызвал ReleaseSemaphore(H,1,nil);
проснулся поток 1, выбрал запрос из очереди, обработал и вновь вызвал Wait ф-ию
пул потоков теперь такой
2
3
1
т.е. следущий запрос будет обрабатывтаь поток 2, затем 3 и так по кругу
и ни один из них не дождется WAIT_TIMEOUT и не уничтожится

PS
эксперимент показал что SetThreadPriority никак не влияет на порядок


 
Игорь Шевченко ©   (2006-02-01 14:03) [8]


> и вызвал ReleaseSemaphore(H,1,nil);
> проснулся поток 1


Разве не все потоки проснулись ?


 
Polevi ©   (2006-02-01 14:04) [9]

с какой радости


 
Polevi ©   (2006-02-01 14:05) [10]

проснется столько сколько я укажу в ReleaseSemaphore


 
Digitman ©   (2006-02-01 14:34) [11]


> проснется столько сколько я укажу в ReleaseSemaphore


здесь, пожалуйста. подробнее ..


 
Polevi ©   (2006-02-01 15:00) [12]

The ReleaseSemaphore function increases the count of the specified semaphore object by a specified amount.
The state of a semaphore object is signaled when its count is greater than zero and nonsignaled when its count is equal to zero.

каждая ожидающая Wait ф-ия умньшит значение счетчика на 1
когда its count is equal to zero. потоки прекратят свое просыпание

странно что я должен вам это обяъснять если честно


 
Digitman ©   (2006-02-01 15:09) [13]


> Polevi ©   (01.02.06 15:00) [12]


> странно что я должен вам это обяъснять


Работу ф-ции мне не надо объяснять - я ее достаточно четко себе представляю.

А не представляю я другое - каким образом кол-во "пробуждаемых" тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore() ..


 
Polevi ©   (2006-02-01 15:13) [14]

напрямую зависит
счетчик=0
10 wait ф-ий ждут пока засигналит объект
я вызвал RS с параметром 2
объект засигналил
в 1 потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =1
объект продолжает сигналить
в 2потоке ф-ия возвратила управление уменьшив значение на 1
счетчик =0
объект не сигналит
оставшиеся потоки ждут след. вызова RS


 
Eraser ©   (2006-02-01 15:17) [15]

по-моему по теме
Тут возникает интересный вопрос. Если несколько потоков ждет один объект ядра, какой из них пробудится при освобождении этого объекта? Официально Microsoft отвечает на этот вопрос так: "Алгоритм действует честно" Что это за алгоритм, Micro soft не говорит, потому что нс хочст связывать себя обязательствами всегда придер живаться именно этого алгоритма. Она утверждает лишь одно- если объект ожидает ся несколькими потоками, то всякий раз, когда этот объект переходит в свободное состояние, каждый из них получает шанс на пробуждение.

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

Рихтер


 
Digitman ©   (2006-02-01 15:29) [16]


> Polevi ©   (01.02.06 15:13) [14]


Спасибо. Это понятно.

Но непонятна твоя прикладная логика, относящаяся к "вызвал RS с параметром 2".

Почему не 3 ? Или не 1 ? Это же важно, согласись..


 
Rouse_ ©   (2006-02-01 15:32) [17]


> А не представляю я другое - каким образом кол-во "пробуждаемых"
> тобой потоков зависит от параметра lReleaseCount ф-ции ReleaseSemaphore()
> ..

По всей видимости у него сделано по такому принципу:

program Project1;

uses
 Windows, Messages, SysUtils, gssocket;

const
 THREAD_COUNT = 4;

var
 hSemaphore: THandle;
 hThread: array [0..THREAD_COUNT - 1] of THandle;
 lpThreadId, lpPreviousCount: DWORD;
 I: Integer;

procedure ThreadProc(lpParameter: Pointer); stdcall;
var
 hThreadSemaphore: THandle;
begin
 case WaitForSingleObject(hSemaphore, 100000) of
   WAIT_OBJECT_0:
     MessageBox(0, PChar("WAIT_OBJECT_0: " + IntToStr(Integer(lpParameter))), nil, MB_OK);
   WAIT_FAILED:
     MessageBox(0, PChar("WAIT_FAILED: " + IntToStr(Integer(lpParameter))), nil, MB_OK);
   WAIT_TIMEOUT:
     MessageBox(0, PChar("WAIT_TIMEOUT: " + IntToStr(Integer(lpParameter))), nil, MB_OK);
 end;
end;

begin
 hSemaphore := CreateSemaphore(nil, 0, THREAD_COUNT, "TestThreadSemaphore");
 if hSemaphore = 0 then
   RaiseLastOSError;
 for I := 0 to THREAD_COUNT - 1 do
   hThread[I] := CreateThread(nil, 0, @ThreadProc, Pointer(I), 0, lpThreadId);
 lpPreviousCount := THREAD_COUNT;
 Sleep(1000);
 if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
 if not ReleaseSemaphore(hSemaphore, 2, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
 if not ReleaseSemaphore(hSemaphore, 1, @lpPreviousCount) then
   RaiseLastOSError;
 Sleep(2000);
end.


Тут наглядно видно. Создается 4 потока. 1 потока отпускаеться через секунду. Потом отпускаються еще два и потом еще один.

Кол-во потоков варьируеться в ReleaseSemaphore


 
Polevi ©   (2006-02-01 15:32) [18]

>Digitman ©   (01.02.06 15:29) [16]
этот параметр равен колву клиентских запросов в очереди


 
Rouse_ ©   (2006-02-01 15:33) [19]

А, ну собственно > Polevi ©   (01.02.06 15:13) [14] сам все рассказал :)


 
Игорь Шевченко ©   (2006-02-01 15:34) [20]

Polevi ©   (01.02.06 15:13) [14]


> оставшиеся потоки ждут след. вызова RS


Или таймаута ?

Я наверное не до конца понимаю, извини

Два рабочих потока ждут освобождения семафора с таймаутом.

Третий поток освободил семафор с ReleaseCount равным единице. Один из потоков проснулся с WAIT_OBJECT_0. Другой поток дождется таймаута ?


 
Polevi ©   (2006-02-01 15:41) [21]

>Игорь Шевченко ©   (01.02.06 15:34) [20]
он его дождется если не будет больше запросов
собственно моя проблема в том, что если один клиент будет каждую секунду посылать запрос - за минуту последовательно проснуться 60 потоков с WAIT_OBJECT_0, до WAIT_TIMEOUT дело не дойдет
вот в случае с LIFO каждый раз бы просыпался поток который посденим вызвал Wait ф-ию а остальные 59 дождались бы таймаута и уничтожились


 
Игорь Шевченко ©   (2006-02-01 15:45) [22]

Polevi ©   (01.02.06 15:41) [21]

Тебе хочется, чтобы на новый запрос просыпался поток, который последним обрабатывал клиентский запрос ? Ты извини за расспросы, я просто понять пытаюсь до конца.


 
Digitman ©   (2006-02-01 15:46) [23]


> Polevi ©   (01.02.06 15:32) [18]
> >Digitman ©   (01.02.06 15:29) [16]
> этот параметр равен колву клиентских запросов в очереди


Тогда вопрос - нашута обрабатывающему некий запрос потоку знать состояние очереди ? Не его это дело ..


 
Rouse_ ©   (2006-02-01 15:53) [24]

Может изменить логику?

1. Пришел запрос - свободных потоков нет - делаем новый, он запрашивает данные и начинает работать.
2. Поток отработал - ставим его на WaitXX (..., INFINITE);
3. Пришел запрос - делаем ReleaseSemaphore. Проснувшийся поток спрашивает свои данные и начинает их выполнять...
Если никто не проснулся, то пункт 1.


 
Polevi ©   (2006-02-01 15:57) [25]

попытаюсь обяснить еще раз что мне надо
у меня наращиваемый пул
необходимо определить условия при которых в него добалвяются и удаляются потоки
алгоритм добавления таков - специальный watch поток следит за очередью клиентских запросов и если находит запрос который лежит там больше X - он добавляет поток в пул
алгоритм удаления был мной сформулирован след. образом - рабочий поток пытается дождаться запроса время Y и если не дожидается - просыпается по таймауту и поняв что делать ему нефиг удаляет себя из пула
допустим в час пик колво потоков достигло 20 а затем пробили куранты все пошли обедать кроме трудоголика васи
вася старательно помылает серверу запросы
вася один а потоков 20
но поскольку работает механизм FIFO на каждый васин запрос будет просыпаться следующий поток, и таймаута ни один из них не дождется

вообщем нужен другой механизм необходимости удаления потока из пула, WAIT_TIMEOUT не подходит


 
Polevi ©   (2006-02-01 15:59) [26]

>Digitman ©   (01.02.06 15:46) [23]
ты не в теме, RS вызывает транспортный поток


 
Polevi ©   (2006-02-01 16:01) [27]

>Rouse_ ©   (01.02.06 15:53) [24]
ну и чем твоя логика отличается от моей интересно

procedure TWorkThread.Execute;
var
 arr:array[0..1] of THandle;
 ir:TInvokeRequest;
 res:TMemoryStream;
 client:TClient;
begin
 arr[0]:=FWaitDataSem;
 arr[1]:=FStopEvent;
 CoInitialize(nil);
 while not Terminated do
 begin
   case WaitForMultipleObjects(2,@arr[0],false,WORKTHREAD_TIMEOUT) of
     WAIT_OBJECT_0: //request
     begin
       ir:=FReqResQueue.GetRequest(client);
       try
         try
           res:=ir.Invoke;
         except on E:Exception do
           res:=CreateExceptionResponse(E.Message);
         end;
         FReqResQueue.AddResponse(client,res);
       finally
         ir.Free;
       end
     end;
     WAIT_TIMEOUT:
     begin
       if FThreadPool.Remove(self) then Terminate;
     end;
     WAIT_OBJECT_0+1: //stop
     begin
       Terminate;
     end
   end;
 end;
 CoUninitialize;
end;


 
Polevi ©   (2006-02-01 16:02) [28]

этот код я привел чтобы показать что после добавления нового потока он обрабатывает запрос и не уничтожается


 
Игорь Шевченко ©   (2006-02-01 16:15) [29]


> но поскольку работает механизм FIFO на каждый васин запрос
> будет просыпаться следующий поток, и таймаута ни один из
> них не дождется


Я вот этого момента честно не понимаю, почему ни один не дождется таймаута ?


 
Digitman ©   (2006-02-01 16:15) [30]


> Polevi ©   (01.02.06 15:59) [26]
> RS вызывает транспортный поток


Тогда поясни, какое дело логике транспортного потока до логики потока-диспетчера пула ?


 
Polevi ©   (2006-02-01 16:27) [31]

>Игорь Шевченко ©   (01.02.06 16:15) [29]
11:00 поток 1 WaitFor(..,10 мин)
11:00 поток 2 WaitFor(..,10 мин)
11:01 request поток 1 WaitFor(..,10 мин)
11:02 request поток 2 WaitFor(..,10 мин)
11:03 request поток 1 WaitFor(..,10 мин)
11:04 request поток 2 WaitFor(..,10 мин)
11:05 request поток 1 WaitFor(..,10 мин)
11:06 request поток 2 WaitFor(..,10 мин)
11:07 request поток 1 WaitFor(..,10 мин)
11:08 request поток 2 WaitFor(..,10 мин)
11:09 request поток 1 WaitFor(..,10 мин)
11:10 request поток 2 WaitFor(..,10 мин)
11:11 request поток 1 WaitFor(..,10 мин)
..
10 мин прошло а таймаута все нет...

>Digitman ©   (01.02.06 16:15) [30]
транспортный поток получил 5 запросов и поместил их в очередь
он сообщает пулу о наличии 5 запросов вызывом RS и идет дальше заниматься своими транспортными делами


 
Игорь Шевченко ©   (2006-02-01 16:45) [32]

Polevi ©   (01.02.06 16:27) [31]


> 10 мин прошло а таймаута все нет...


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


 
Rouse_ ©   (2006-02-01 16:48) [33]


> но поскольку работает механизм FIFO на каждый васин запрос
> будет просыпаться следующий поток, и таймаута ни один из
> них не дождется

тогда уйди от семафора и перейди на собственный механизм. т.е. некий контролируйщий поток содержит в себе массив, ну... к примеру Event-ов. Все остальные потоки ждут сигнала только от своего Event-а. При срабатывании WaitXX в этом контролирующем потоке, он по нужному тебе алгоритму сделает SetEvent нужному тебе элементу. остальные выйдут по таймауту.


 
Polevi ©   (2006-02-01 16:49) [34]

>Игорь Шевченко ©   (01.02.06 16:45) [32]
уфф, ну наконец чтото конкретное :-)
я собственно и думаю над алгоритмом, принимаю ваши предложения


 
Polevi ©   (2006-02-01 16:56) [35]

>Rouse_ ©   (01.02.06 16:48) [33]
а как я узнаю какой из них нужный
может он занят и освободится через час :)
к тому же их может потребоваться больше одного за раз


 
Игорь Шевченко ©   (2006-02-01 17:02) [36]

Polevi ©   (01.02.06 16:49) [34]

WaitFor(...., DefaultTimeout div NumberOfWorkerThreads).

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


 
Polevi ©   (2006-02-01 17:09) [37]

>Игорь Шевченко ©   (01.02.06 17:02) [36]
спасибо, так я и сделаю


 
Rouse_ ©   (2006-02-01 17:28) [38]


> а как я узнаю какой из них нужный
> может он занят и освободится через час

Флаг состояния держать :)


> к тому же их может потребоваться больше одного за раз

за раз не получиться, только по очереди :)


 
Набережных С. ©   (2006-02-01 17:33) [39]


> Polevi ©   (01.02.06 15:57) [25]

Я бы посоветовал для такой задачи использовать Completion Port. Во первых, он использует как раз LIFO, во вторых использует эффективный алгоритм управления количеством активных потоков.

И по поводу алгоритма. Лучше, ИМХО, периодически, ну скажем, раз в 30 секунд проверять три параметра - средняя загрузка процессоров, количество активных потоков и количество ожидающих потоков. И где-нибудь раз в 3-5 минут корректировать при необходимости количество потоков в пуле. Желательно также накапливать и учитывать при этом кое-какую статистику по распределению нагрузки в течении суток.

Кстати, пример возможного варианта реализации пула с использованием порта завершения есть вот здесь: http://kladovka.net.ru/index.cgi?pid=board&rid=298, но собственно пул - дело несложное. Правда, механизма оптимизации там нет, так как его вряд ли можно сделать универсальным, оторванным от конкретной ситуации.


 
Набережных С. ©   (2006-02-01 17:39) [40]


> Лучше, ИМХО, периодически, ну скажем, раз в 30 секунд проверять
> три параметра

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


 
Игорь Шевченко ©   (2006-02-01 17:43) [41]

Набережных С. ©   (01.02.06 17:39) [40]

А вот с числом потоков тут непросто, так как все зависит от задачи. Если обработка запроса ведет к монополизации процессора, то конечно, чем меньше потоков на один процессор, тем лучше, а если нет, то почему бы и  (не сто, а, скажем, 10-20 потоков) не держать ?


 
Набережных С. ©   (2006-02-01 18:03) [42]


> Игорь Шевченко ©   (01.02.06 17:43) [41]


> Если обработка запроса ведет к монополизации процессора,
>  то конечно, чем меньше потоков на один процессор, тем лучше,
>  а если нет, то почему бы и  (не сто, а, скажем, 10-20 потоков)
> не держать ?

Да, конечно. Но я имел в виду именно активные потоки, монополизирующие процессор. И тут как раз порт завершения оказывается очень кстати, потому, что учитывает именно эти потоки, отбрасывая ожидающие чего либо, как известно. Без Completion Port такую функциональность получить непросто. Кстати, по приведенной мной ссылке есть и второй вариант пула, как раз для тех случаев, когда нужно активировать очередной поток независимо от загруженности.


 
Игорь Шевченко ©   (2006-02-01 18:08) [43]

Набережных С. ©   (01.02.06 18:03) [42]

<offtopic>

А вот в Vista, похоже, задача автора решается новыми API-функциями :)

</offtopic>


 
Polevi ©   (2006-02-01 18:21) [44]

>Набережных С. ©   (01.02.06 17:33) [39]
c загрузкой процессора и колво активных потоков врядли получится
дело в том что собствено задача - некий маршаллер, задача которго создать нужный COM объект и вызвать для него IDispatch.Invoke
что это за объект и что он делает маршаллер не знает
в основном объекты работат с БД
насчет порта завершения - откуда информация что он использует LIFO и есть ли уверенность что майкрософт не изменит алгоритм ?


 
Polevi ©   (2006-02-01 18:33) [45]

и наколько я понял NumberOfConcurrentThreads можно задать только один раз при создании порта
мне же это колво надо менять динамически
объекты работают с БД, поток может висеть из за блокировки ресурса к примеру


 
Набережных С. ©   (2006-02-01 19:31) [46]


> Игорь Шевченко ©   (01.02.06 18:08) [43]

Замечательно, если так, задача-то не из простых. Особенно, если будет достаточно возможностей тонкой настройки.

> Polevi ©   (01.02.06 18:21) [44]


> c загрузкой процессора и колво активных потоков врядли получится

Почему? Загрузка легко измеряется счетчиком производительности. А с активными потоками - тебя должны будут интересовать только потоки твоего пула как индикатор активности пользователей, а их отследить не сложно. За активацию по мере освобождения процессора будет отвечать порт завершения, причем он будет учитывать именно реальное использование процессора. В том то и прелесть, что он позволяет максимально полно использовать минимизируя при этом непроизводительные потери на переключение потоков.

> насчет порта завершения - откуда информация что он использует
> LIFO

Ну как минимум от Рихтера. Где-то у него об этом есть довольно подробно. Далее собственные экспиременты. Ну и в MSDN вроде как тоже что-то видел по этому поводу.

> есть ли уверенность что майкрософт не изменит алгоритм ?

А нафига? Ты можешь предложить что-ни будь более эффективное?:)) Если запускать первым последний вошедший поток, то есть немалая вероятность, что этот поток еще не успел заснуть и, следовательно, получится экономия на работе с контекстом. Зачем же это менять? Да и не надо тебе заботиться, какой именно поток убивать. Какая разница? Главное, что их общее количество будет соответствовать ситуации, а об остальном позаботится порт.

> и наколько я понял NumberOfConcurrentThreads можно задать
> только один раз при создании порта
> мне же это колво надо менять динамически
> объекты работают с БД, поток может висеть из за блокировки
> ресурса к примеру

Да зачем же их менять?:) Это же количество одновременно активных потоков. Что, у тебя количество процессоров изменится во время работы?:))

> поток может висеть из за блокировки ресурса к примеру

Да пусть себе висит:) Как только какой-то поток перестанет использовать процессор, порт тут-же активирует новый поток, если в очереди есть запросы и есть ожидающий поток. А ожидающих ты можешь создать столько, сколько потребуется.

Пусть имеем 1 процессор. Создаем порт, задав ему 1 "конкурирующий" поток. Создаем 5 потоков и все их подключаем к порту. Постуил запрос, порт разбудил 1 поток, тот начал обработку. Допустим тут пришли еще несколько запросов - порт на них не реагирует. Тут активный поток обращается к девайсу и начинает ждать от него ответа, т.е. процессор ему не нужен. Порт тут же отреагирует на это и активирует следующий поток из подключенных к нему. Если и второй поток перейдет к ожиданию чего-либо, то порт тут же разбудит следующий поток. Т.е. порт не даст процессору простаивать, пока есть запросы в очереди и готовые их принять потоки. Разумеется, потом наступит момент когда требующих доступа к процессору потоков окажется больше, чем число процессоров и тут неизбежны переключения контекстов. Но, во-первых, такое положение продлится не долго, а во-вторых если проанализировать, то это все равно наилучший сценарий поведения из всех возможных - при других вариантах издержек оказывается больше.


 
Набережных С. ©   (2006-02-01 19:38) [47]


>что он позволяет максимально полно использовать минимизируя
> при этом

"он позволяет максимально полно использовать процессоры, минимизируя при этом" и далее по тексту:)


 
Polevi ©   (2006-02-02 08:19) [48]

>Набережных С. ©   (01.02.06 19:31) [46]
дa, насчет NumberOfConcurrentThreads я запамятовал, туда 0 в моем случае надо передавать
написал тест все чудно работает, действительно LIFO, то что мне надо

вопрос с одновременным пробуждением нескольких потоков тоже элегантно решается передачей в PQCS счетчика

procedure TT.Execute;
var
 bytes,key:Cardinal;
 ov:POVERLAPPED;
begin
 while not Terminated do
 begin
   if GetQueuedCompletionStatus(H, bytes, key, ov, 5000) then
   begin
     if bytes>1 then
       PostQueuedCompletionStatus(H,bytes-1,0,nil);
     ...
     ...
     ...
   end
   else
   if GetLastError()=WAIT_TIMEOUT then break;
 end;
end;

спасибо за идею


 
Набережных С. ©   (2006-02-02 17:07) [49]


> Polevi ©   (02.02.06 08:19) [48]

Извини за назойливость:), но я как-то не удовил, зачем рабочий поток вызывает PostQueuedCompletionStatus. Есть у транспорта 5 запросов - пусть он и вазывает эту функцию 5 раз подряд, а дело рабочих потоков - эти запросы обрабатывать. Или у тебя потоки занимаются и тем, и другим? Я так определял два ключа  - CPKEY_RESTART и CPKEY_TERMINATE - и ими управлял. Если проснувшись поток получал CPKEY_TERMINATE, то он завершался, а если CPKEY_RESTART, то забирал очередную задачу из списка и обрабатывал ее. И насчет использование таймаутов тоже подумай еще раз. Потоки лучше удалять, когда больше делать нечего, а когда запросы более-менее регулярно приходят, лучше на это не отвлекаться. Ну висят без дела 5-10 лишних потоков - ну и пусть себе висят, кому они мешают? Наступит перерыв, тогда и удалить их можно. Да и желательно всегда иметь резерв на случай внезапного "взрыва" активности, а то навалятся запросы, а ты будешь тратить время на создание потоков, которые только что уничтожал.
IMHO, разумеется.


 
Polevi ©   (2006-02-03 09:32) [50]

>Набережных С. ©   (02.02.06 17:07) [49]
по поводу PQCS в рабочем потоке - так я избавился от цикла в транспортном потоке, т.е вызов ReleaseSemaphore(cnt) заменил на PostQueuedCompletionStatus(cnt), но можно было и цикл, конечно
ключи у меня определены аналогично твоим
я немного оттюнинговал проект, увеличил минимальное колво потоков в пуле до 5, время таймаута рабочего потока до 5 мин
процесс добавления , удаления потоков в пуле протоколируется вместе с информацией о минимуме-максимуме клиентов и потоков
запустил в работу один офис - это порядка 20 клиентов..
на основе логов возможно поменяю значения констант



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

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

Наверх




Память: 0.62 MB
Время: 0.019 c
6-1136934287
Кефир87
2006-01-11 02:04
2006.04.23
HTTP клиент с помощью TClientSocket


15-1143993758
ArtemESC
2006-04-02 20:02
2006.04.23
С помощь чего можно...


15-1144093886
Petr V. Abramov
2006-04-03 23:51
2006.04.23
Oracle 10 Release 2


2-1144259729
Yegorchic
2006-04-05 21:55
2006.04.23
TMainMenu.ShortCut


15-1143721344
Mike Kouzmine
2006-03-30 16:22
2006.04.23
Не успели запустить бразильца в космос, как





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