Re: BeginInvoke failing when executed in a form that was created in a worker thread...



On May 28, 12:59 pm, Mehdi <vio...@xxxxxxxxxxxxxxxxxx> wrote:
On 28 May 2007 12:25:17 -0700, Ian Mac wrote:

In summary, if GUI thread 'A' spawns a worker thread 'B', and worker
thread 'B' instantiates an instance of my component, then if threads
'C', 'D', 'E', or whatever make calls to 'RaiseNewEvent', the actual
events MUST be raised on thread 'B' (the thread where the component
was initially created). I believe that there's absolutely no way to
achieve this type of functionality in .NET, but I'm hoping you or
someone can tell me otherwise.

Right on top of my head, I effectively can't think of anything that would
fit your requirements. However, if you can modify your requirements
slightly, things become a lot easier:

Suggestion 1: implement a producer/consumer algorithm. For example, in the
constructor of your event raising component (which is called in thread B)
create a queue and start a new thread, say thread BB. In this new thread,
wait on an AutoResetEvent (that will put thread BB to sleep). Whenever
thread C, D or E wants an event to be raised, enqueue the event's data in
the queue then signal the AutoResetEvent. This will wake up thread BB which
can then dequeue the event's data and raise the event (you of course need
to synchronize access to the queue). All the events will therefore be
raised in thread BB (but not in thead B).

Suggestion 2: see if there is any valid reason why the events can not be
always raised in the UI thread. Things would be a lot easier if you could
simply require your component to be created in the UI thread then use the
method suggested in your original message to marshall all the events to the
UI thread.

Suggestion 3: see if there is any valid reason to require all the events to
be always raised in the same thread. Maybe you don't really need to go
through all this trouble and can simply raise the events in any thread.


Thanks Mehdi.

Suggestion 1 won't work because thread 'B' (where the component was
created) needs to be doing work other than just servicing the synch'ed
Q, and thus when it creates an instance of FEventRaiser, FEventRaiser
must NOT put the thread in a wait-state looking for AutoResetEvent
events. This was the whole reason for the event-raising component in
the first place...the user of the component can carry on doing what it
normally does, and only needs to respond to the FEventRaiser's
'MyEvent' event.

As for suggestions 2 and 3 , the reason I discovered the behavior I
originally posted was because I had a valid need to do exactly what I
posted. The code I posted has been in use for a couple of years, and
since nobody has ever tried instantiating the class in a thread other
than the GUI thread, it's always worked flawlessly, but a few days
ago, I tried creating an instance of a class (let's call it
CMyClass), that internally makes use of FEventRaiser, on a worker
thread, and the object failed to operate as it would/should had I
created it on the GUI thread. Since class CMyClass does some work that
can potentially block the thread it was created on for several seconds
(specifically, in the 'MyEvent' event raised from FEventRaiser),
instantiating CMyClass in the UI thread is no good.

I'd really like to know the technical reason why the message pump
behind FEventRaiser's form stops getting serviced simply because the
form was created in a worker thread. Perhaps if I knew this, it would
give me a clue as to how to make it work (either as is, or even taking
a completely different approach...as long as I can keep it black-box
and not break existing users of the component).

Thanks.

Ian


.



Relevant Pages

  • Re: BeginInvoke failing when executed in a form that was created in a worker thread...
    ... Suggestion 1: implement a producer/consumer algorithm. ... see if there is any valid reason to require all the events to ... Q, and thus when it creates an instance of FEventRaiser, FEventRaiser ... CMyClass), that internally makes use of FEventRaiser, on a worker ...
    (microsoft.public.dotnet.framework.windowsforms)
  • Re: Timer or worker thread
    ... The suggestion sounds fairly reasonable. ... However, I would use only one waitable timer, ... rollowever of month, year, etc.) which is one reason COleDateTime is probably a good ... because it would mean that the GUI thread was dead, which would be a very bad thing. ...
    (microsoft.public.vc.mfc)
  • Re: Reports from Comic-Con
    ... stuff because the pre-ordered discs contain no comic even though no ... Perhaps I didn't phrase my suggestion properly then. ... Know what likely happened to your carefully explained reason for returning ... Online ads on B5 or other SF sites? ...
    (rec.arts.sf.tv.babylon5.moderated)
  • Re: Row cannot be located for updating. Some values may have been changed since it was last read
    ... Yes I try the Kevin's suggestion and I still have the problem. ... But the property available to do this (Update Criteria) is ... Is it the reason why I change my ... dataset's properties to adCriteriaKey: ...
    (borland.public.delphi.database.ado)

Quantcast