Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.12.13;
Скачать: CL | DM;

Вниз

Windows Script Host + COM + ThreadPool   Найти похожие ветки 

 
K1LLADR1LLA ©   (2008-10-27 17:53) [0]

Значит так.
Есть пул потоков QueueUserWorkItem, в callback методе
потока очереди
инициализится COM и создаётся COM-объект(Perl-скрипт мутящий текстовый файл по регулярному выражению).

К примеру, я создаю пул из 60 потоков и пихаю в каждый поток по одному заданию(текст+регулярное выражение), так вот странным образом, хотя и создаётся очередь из 60 потоков, обрабатывается корректно примерно 95% очереди, некотрорые потоки из пула странным образом не выполняются, и при этом никаких эксэпшынов не происходит в потоке.
Господа, что это может быть, в чем я туплю ?
=======CALLBACK функция для QueueUserWorkItem=========
function qGrepex(Value:Pointer):dword; stdcall;
//label LOOP;
var
 outs,rx,txt:string;
 ghost : OleVariant;
 val : TSIREXSValue;
 I: Integer;
begin
try
 Val    := TSIREXSValue(Value^);
 rx     := val.rx;
 txt    := val.txt;
           try
             CoInitializeEx
           (nil,COINIT_APARTMENTTHREADED);
            Ghost := CreateOleObject("psirexuwz.wsc"); //
           finally
 InterlockedIncrement(SIUtils.GPooled);
    Ghost.grepex(rx,txt);   // вызываю метод из скрипта.
 while outs="" do sleep(50);
 InterlockedDecrement(SIUtils.GPooled);
 InterlockedDecrement(siutils.GEventCounter);
 CoUninitialize;
end;
except
 on E:Exception do Tsrvc.PostLog("qGrepex :: "+E.Message);
end;
result := 0ж
end;
==================================================
====================Perl-скрипт=====================

<?xml version="1.0"?>
<component>

<?component error="true" debug="true"?>

<registration
description="psirexuwz"
progid="psirexuwz.WSC"
version="2.00"
classid="{dabdb3f5-197a-403f-bc59-68094655e5f7}"
>
</registration>

<public>
<method name="grepex" dispid = "1">
 <PARAMETER name="RegexPattern"/>
 <PARAMETER name="Filename"/>
</method>
                  <method name="stoop" dispid="2">
 
                  </method>
</public>

<script language="PerlScript">
<![CDATA[
#use strict;
   use threads;

use File::Basename;
my $wrk=0;

sub get_sum_len
{
  my ($x,@indata);
  my ($res,$i) = 0;
  my  @dout;
  ($x,@indata) = @_;
   for($i=0;$i<$x;$i++)
   {
     $res = ($res + length($indata[$i]));
     $dout[$i] = $i<=0?$res:$res-length($indata[$i]);
   }  
   return @dout;
}
sub grepex{
  open(in0,$_[0]);
  open(in00,$_[1]);
  open(in000,">".dirname($_[0])."\\xfile");
  exit if -e dirname($_[0])."\\rslt";
  my $d1r = ">".dirname($_[0])."\\rslt";
  open(out0,$d1r);
  my (@data,@dout,@expr,@res);
  my ($dlen,$exp,$cnt,$j) ;
  my ($i,$cpos,$gcpos,$llen,$flag);  
  @data = <in00> ;
  @expr = <in0>  ;
  $dlen = scalar(@data);
  @dout = get_sum_len($dlen,@data);  
  eval
  {
  foreach $exp(@expr)
  {
     if($wrk == 0)
  {
   $cnt+=1;
   for($i=0;$i<$dlen;$i++)
   {  
     while($data[$i]=~m/$exp/gxc)    
     {    
         $cpos  = (pos($data[$i]) - length($&))  ;
         $gcpos = ($dout[$i] + $cpos);        
         $res[$j++] = $cnt."p".      
         ($gcpos+($i)."l".length($&))."m".$&."\n";
     }
    }    
   }
  }
 }

   $res[0]=$@ if $@;
   $res[0]=($res[0] eq ""? "$nrslt$":$res[0]);
   
     print out0 @res;
     close(out0);
   close(in0);
   close(in00);
   return join("",@res);  
   @res="";    
}

====================Perl-скрипт=====================
]]>
</script>

</component>


 
Сергей М. ©   (2008-10-27 21:28) [1]


> в чем я туплю ?


Первая же "тупость", бросающаяся в глаза:


> while outs="" do sleep(50);


Что это за танцы с бубном ?
Кто и где изменяет содержимое переменной outs, так чтобы выполнилось условие выхода из цикла ?


 
Slym ©   (2008-10-28 04:53) [2]

а разве так можно?
CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
а CALLBACK функция для QueueUserWorkItem может менять поток (если не WT_EXECUTEINPERSISTENTTHREAD), т.е. с COM объектом созданным в одном потоке работа может происходить в нескольких других потоках тем более что ты принудительно усыпляешь sleep поток что может повлеч за собой переключение потока на другой колбек

http://vsokovikov.narod.ru/New_MSDN_API/Process_thread/thread_pool.htm

Обратите внимание! на то, что объединение потоков в пул не совместимо с моделью однопоточных апартаментов (STA).


 
K1LLADR1LLA ©   (2008-10-28 09:37) [3]

ааа,
while outs="" do sleep(50);
это я забыл закаментить, это сейчас не используется.
это я сделал для того, что бы поток из пула дождался результата из скрипта, потому как я думал, что поток завершается преждевременно.
-----------------------------------------------------------------------
Самое интересное, что с этим-то флагом COINIT_APARTMENTTHREADED, всё работает нормально, потоки добавляются в пул ,но как я уже сказал, всреднем, 5% потоков не выполняются корректно , хотя никаких исключений не вылазит. Если же ставлю флаг COINIT_MULTITHREADED, то пул так же создается, но активно выполняется один поток, все остальные ждут и в этом случае всё потоки выполняют работу корректно.
Скрипт регистрируется в реестре с ключём InprocServer32->ThreadingModel->Apartment


 
Slym ©   (2008-10-28 11:54) [4]

ну все верно... когда по очереди все нормально проходят через узкую дверь... а когда "толпой" 5% в давке загибаются...
попробуй 1 раз COINIT_MULTITHREADED перед запуском пула, из калбека убери может само "синхронизируется" :)


 
K1LLADR1LLA ©   (2008-10-28 13:13) [5]

пардон , я нагнал, даже когда COINIT_MULTITHREADED , и работает один поток, всё-равно пропускает задания, казлина )=


 
Slym ©   (2008-10-28 13:31) [6]

не проще пересмотреть задачу и наити другое более линейное решение? без пула никак? в 1 потоке? или в CPUCount потоках?
я к тому что всеравно активно будет не более CPUCount потоков...

CreateOleObject("psirexuwz.wsc") креатится постоянно... зачем? он stateless


 
Slym ©   (2008-10-28 13:38) [7]

Slym ©   (28.10.08 13:31) [6]
пулы не для этого придуманы...
придуманы они для распараллеливания часто простаивающих процедур для минимизации колва потоков и расходов с ними связанных: переключения потоков, стекпамять и т.п. и т.д.

Но у тебя узкое место далеко не этом... только хуже делаешь...
расходы при взаимодействии с COM подсистемой CoInitializeEx/CoUninitialize/CreateOleObject("psirexuwz.wsc") намного превысят "доходы" от QueueUserWorkItem


 
K1LLADR1LLA ©   (2008-10-28 13:59) [8]

CreateOleObject("psirexuwz.wsc") креатится постоянно... зачем? он stateless
----------------------------------------------------------------------------
если я создаю единожды CreateOleObject("psirexuwz.wsc") в другом потоке, и передаю OleVariant переменную в callback метод потока, то вылазит экцэпшн... но я перепроверю ещё раз.
----------------------------------------------------------------------------
не проще пересмотреть задачу и наити другое более линейное решение? без пула никак? в 1 потоке? или в CPUCount потоках?
----------------------------------------------------------------------------
Дело в том что, на вычисление регулярного выражения будут поступать огромные логи до 1ГБ, с множества (до 10000) клиентов, поэтому было решено юзать пул. Ну тоесть один раз при старте сервиса создаётся определённое кол-во потоков, в которые пихаются задачи.


 
Slym ©   (2008-10-28 14:12) [9]

K1LLADR1LLA ©   (28.10.08 13:59) [8]
на вычисление регулярного выражения будут поступать огромные логи до 1ГБ

ИЧЁ? стопудофф линейно без пулофф (при текущей реализации) быстрее буит...

програм1

делаем потоки по колву процессоров

впотоке.еХекут
{
КоИнит;
обж:=КреатОбжект("psirexuwz.wsc");
дотехпорпокаживу дуит
{
задача:=ядро.дайзадачу
обж.коитус(задача)
ядро.яеёоткоитовал(задача)
}
КоДеИнит;
}


 
Slym ©   (2008-10-28 14:19) [10]

смысла перевода непосредственного выполнения кода в теле потока в APC спящего потока я не вижу...


 
K1LLADR1LLA ©   (2008-10-28 14:34) [11]

мг, я буду иметь ввиду выше предложенное, хотя я уже мудохаюсь неделю ((=
Если смысла не видно, то это ещё не значит, что смысла нет ((=



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

Текущий архив: 2009.12.13;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.015 c
3-1231348460
TCrash
2009-01-07 20:14
2009.12.13
Получение полного имени поля


2-1256122896
stas
2009-10-21 15:01
2009.12.13
Использование LogonUser


2-1256138283
Дедушка мазай
2009-10-21 19:18
2009.12.13
Как отключить правую кнопку мыши


15-1255158192
vrem
2009-10-10 11:03
2009.12.13
Поздравляю с днём психического здоровья..


2-1256109863
RWolf
2009-10-21 11:24
2009.12.13
AnsiExtractQuotedStr(PChar(str), ...)