multithreading - Can TOmniEventMonitor be used in a background thread? -


original question

in our delphi xe4 application use tomnieventmonitor receive messages other tasks. long running in main thread, works fine, once put same code in task, tomnieventmonitor stops receiving messages. have included simple example of below -- clicking button_testinmainthread results in file being written expected, clicking button_testinbackgroundthread not. design, or there way working while still using tomnieventmonitor?

unit mainform;  interface  uses   winapi.windows, winapi.messages,   system.sysutils, system.variants, system.classes,   vcl.graphics,vcl.controls, vcl.forms, vcl.dialogs, vcl.stdctrls,   otltask, otltaskcontrol, otlcomm, otleventmonitor;  const   my_omni_message = 134;  type   tomnieventmonitortester = class(tobject)     fname : string;     fomnieventmonitor : tomnieventmonitor;     fomnitaskcontrol : iomnitaskcontrol;     constructor create(aname : string);     destructor destroy(); override;     procedure handleomnitaskmessage(const task: iomnitaskcontrol; const msg: tomnimessage);   end;    ttestlaunchertask = class(tomniworker)     fomnitaskmonitortester : tomnieventmonitortester;     function initialize() : boolean; override;   end;    tform1 = class(tform)     button_testinmainthread: tbutton;     button_testinbackgroundthread: tbutton;     procedure button_testinmainthreadclick(sender: tobject);     procedure button_testinbackgroundthreadclick(sender: tobject);   private     fomnieventmonitortester : tomnieventmonitortester;     ftestlaunchertask : iomnitaskcontrol;   end;  var   form1: tform1;  implementation  {$r *.dfm}   procedure omnitaskprocedure_oneshottimer(const task: iomnitask); begin   sleep(1000);   task.comm.send(my_omni_message); end;  constructor tomnieventmonitortester.create(aname : string); begin   inherited create();   fname := aname;   fomnieventmonitor := tomnieventmonitor.create(nil);   fomnieventmonitor.ontaskmessage := handleomnitaskmessage;   fomnitaskcontrol := fomnieventmonitor.monitor(createtask(omnitaskprocedure_oneshottimer)).run(); end;  destructor tomnieventmonitortester.destroy(); begin   fomnieventmonitor.free();   inherited destroy(); end;  procedure tomnieventmonitortester.handleomnitaskmessage(const task: iomnitaskcontrol; const msg: tomnimessage); var   filename : string;   f : textfile; begin   filename := includetrailingpathdelimiter(extractfiledir(paramstr(0))) + fname + '.txt';   assignfile(f, filename);   rewrite(f);   writeln(f, fname);   closefile(f); end;  function ttestlaunchertask.initialize() : boolean; begin   result := inherited initialize();   if result begin     fomnitaskmonitortester := tomnieventmonitortester.create('background');   end; end;  procedure tform1.button_testinmainthreadclick(sender: tobject); begin   fomnieventmonitortester := tomnieventmonitortester.create('main'); end;  procedure tform1.button_testinbackgroundthreadclick(sender: tobject); begin   ftestlaunchertask := createtask(ttestlaunchertask.create()).run(); end;  end. 

additional observations

with following code seems possible use tomnieventmonitor within background thread. clumsy solution -- iomnitwowaychannel gets created not used in meaningful way -- try simplify code commenting out either of lines marked "don't remove!", handletaskmessage doesn't called more. can tell me doing wrong here?

unit mainform;  interface  uses   winapi.windows, winapi.messages,   system.sysutils, system.variants, system.classes,   vcl.graphics, vcl.controls, vcl.forms, vcl.dialogs, vcl.stdctrls,   dsiwin32, gplists, otltask, otltaskcontrol, otlcommon, otlcomm, otleventmonitor;  const   my_omni_message = 134;  type    tomnieventmonitortesttask = class(tomniworker)     fomnitaskcontrol : iomnitaskcontrol;     fomnitwowaychannel : iomnitwowaychannel;     fomnieventmonitor : tomnieventmonitor;     function  initialize() : boolean; override;     procedure handletaskmessage(const task: iomnitaskcontrol; const msg: tomnimessage);     procedure handletaskterminated(const task: iomnitaskcontrol);   end;    tform1 = class(tform)     button_testinbackgroundthread: tbutton;     procedure button_testinbackgroundthreadclick(sender: tobject);   private     ftesttask : iomnitaskcontrol;   end;  var   form1: tform1;  implementation  {$r *.dfm}  procedure omnitaskprocedure_oneshottimer(const task: iomnitask); begin   sleep(1000);   task.comm.send(my_omni_message); // don't remove!   (task.param['comm'].asinterface iomnicommunicationendpoint).send(my_omni_message); end;  procedure tomnieventmonitortesttask.handletaskmessage(const task: iomnitaskcontrol; const msg: tomnimessage); var   filename : string;   f : textfile; begin   filename := includetrailingpathdelimiter(extractfiledir(paramstr(0))) + 'handletaskmessage.txt';   assignfile(f, filename);   rewrite(f);   writeln(f, 'handletaskmessage!');   closefile(f); end;  procedure tomnieventmonitortesttask.handletaskterminated(const task: iomnitaskcontrol); var   filename : string;   f : textfile; begin   filename := includetrailingpathdelimiter(extractfiledir(paramstr(0))) + 'handletaskterminated.txt';   assignfile(f, filename);   rewrite(f);   writeln(f, 'handletaskterminated!');   closefile(f); end;  function tomnieventmonitortesttask.initialize() : boolean; begin   result := inherited initialize();   if result begin     fomnieventmonitor := tomnieventmonitor.create(nil);     fomnieventmonitor.ontaskmessage := handletaskmessage;     fomnieventmonitor.ontaskterminated := handletaskterminated;     fomnitwowaychannel := createtwowaychannel();     task.registercomm(fomnitwowaychannel.endpoint1); // don't remove!     fomnitaskcontrol := fomnieventmonitor.monitor( createtask(omnitaskprocedure_oneshottimer) ).setparameter('comm', fomnitwowaychannel.endpoint2).run();   end; end;  procedure tform1.button_testinbackgroundthreadclick(sender: tobject); begin   ftesttask := createtask(tomnieventmonitortesttask.create()).run(); end;  end. 

there no problem tomnieventmonitor running inside of thread, provided there message pump handling messages it. put block of code demonstrate. works expected.

procedure tmythread.execute; var   message: tmsg; begin   freeonterminate := true;   fomnieventmonitor := tomnieventmonitor.create(nil);   fomnieventmonitor.ontaskmessage := handleomnitaskmessage;   fomnitaskcontrol := fomnieventmonitor.monitor(createtask(omnitaskprocedure_oneshottimer)).run();   try     while not terminated     begin       if msgwaitformultipleobjects(0, nil^, false, 1000, qs_allinput) = wait_object_0       begin         while peekmessage(message, 0, 0, 0, pm_remove)         begin           translatemessage(message);           dispatchmessage(message);         end;       end;     end;       fomnitaskcontrol := nil;     fomnieventmonitor.free;   end; end; 

from can see, tomnitaskexecutor waits messages specific handles. in code example, it's terminate event , couple of comm handles. messages tomnieventmonitor never processed.

changing ttestlaunchertask.initialize following results in correctly writing out file. donothingproc empty method on class.

function ttestlaunchertask.initialize() : boolean; begin   result := inherited initialize();   if result begin     fomnitaskmonitortester := tomnieventmonitortester.create('background');     // tell task event monitor     task.registerwaitobject(fomnitaskmonitortester.fomnieventmonitor.messagewindow, donothingproc);   end; end; 

i adding message window tomnieventmonitor task waitobject list handle registered msgwaitformultipleobjectsex call , waiting remi , david tear message handling shreds :)


Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -