> I'll try to explain my situation as clearly as possible. J
>
[quoted text clipped - 19 lines]
>
> Mark
> your flaw is visible in the description: don't have the worker thread call
> Invoke when it captures an abort.
>
> If you get an abort, simply end the thread. Let the U/I, which issued the
> abort, handle updates to the U/I.
Thanks Jon and Nick for your responses. Interesting suggestions. If I
understand correctly, we've got three ideas here:
1. Don't use abort (or indeed join), but use a signalling flag to indicate
that the worker thread should stop. Have the worker thread check this flag
at each iteration and shutdown as appropriate. This looks like a nice clean
solution. The problem that I'm having is that the worker thread has a stage
that could take many seconds (i.e. too long for the user) before checking
the flag. This could leave the UI saying "worker thread stopping..." for too
long. I suppose it might be possible to recode the worker to recheck the
stop flag at more regular intervals, but I'm dependent on waiting for the OS
to time out on open files, so that might not be practical (and the code can
get messy).
2. Don't invoke from the worker thread, but let the UI thread handle the
update to the UI instead. Interesting idea: it means that the UI will have
to monitor and wait for the thread to finish. (A sort of join but without
using join?) I did read somewhere that joins should be avoided in UI threads
as they can theoretically (i.e. with buggy code in the worker) cause the UI
to hang. Thoughts? To me it does seem more logical to have the worker thread
telling the UI what it is doing - including stopping naturally and aborting
than have the UI thread reporting it. I'll think about this more.
3. Use BeginInvoke from the worker thread. This worked a treat! Indeed this
is the idea on MSDN where the author (Chris Sells) states that you should
use BeginInvoke rather than Invoke even from worker threads as it reduces
the chances of a deadlock (though he doesn't use endinvoke even though those
nice chaps in the .net framework runtime department have reserved the right
to be leaky without an endinvoke!). To me, this leads to an interesting
conceptual thought... The UI thread is sitting at a join waiting on the
worker thread. The worker thread puts a UI update message onto the UI thread
via a BeginInvoke but then carries on to exit. The UI thread continues past
the join and the UI update message gets handled by the UI thread after the
worker thread has stopped. This may be "normal" practice, but to me it's
sort of strange that the thread closes before the UI message that says "i'm
closing..." gets to the UI! Probably just academic interest. :-)
So where does this leave me? Well I have solutions, none of which fill me
with a sense of Nirvana but which do nevertheless work. :-) I do like the
idea of not using aborts if possible and using some signalling flag instead,
but I do want to guarantee that I can close the thread after a predefined
timeout should something go wrong in the worker thread as its closing. That
is, trying a tidy shutdown but resorting to an abort if necessary. Looks
like a manualresetevent and waitone might help me here?
Thanks again
Mark
> --- Nick
>
[quoted text clipped - 27 lines]
>>
>> Mark
Jon Skeet [C# MVP] - 12 Dec 2004 13:41 GMT
> 3. Use BeginInvoke from the worker thread. This worked a treat! Indeed this
> is the idea on MSDN where the author (Chris Sells) states that you should
> use BeginInvoke rather than Invoke even from worker threads as it reduces
> the chances of a deadlock (though he doesn't use endinvoke even though those
> nice chaps in the .net framework runtime department have reserved the right
> to be leaky without an endinvoke!).
You don't need to call EndInvoke for calls to Control.BeginInvoke, even
though you do for general BeginXXX/EndXXX calls. The WinForms team has
said they *won't* leak things here.
<snip>
> So where does this leave me? Well I have solutions, none of which fill me
> with a sense of Nirvana but which do nevertheless work. :-) I do like the
[quoted text clipped - 3 lines]
> is, trying a tidy shutdown but resorting to an abort if necessary. Looks
> like a manualresetevent and waitone might help me here?
I don't think you need a ManualResetEvent here - just start a timer
which you either cancel or ignore if the orderly shutdown has worked.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Mark - 12 Dec 2004 19:23 GMT
>> 3. Use BeginInvoke from the worker thread. This worked a treat! Indeed
>> this
[quoted text clipped - 9 lines]
> though you do for general BeginXXX/EndXXX calls. The WinForms team has
> said they *won't* leak things here.
Interesting. I found the reference on MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cp
ovrasynchronousprogrammingoverview.asp
Admitedly, it doesn't say that if you _don't_endinvoke it'll leak, which
kind of begs the question why the MDSN caution says what it does. I did read
somewhere, could be bogus though, that someone had tested begininvokes
without endinvokes and discovered a leak. Oh well, c'est la via.
> <snip>
>
[quoted text clipped - 10 lines]
> I don't think you need a ManualResetEvent here - just start a timer
> which you either cancel or ignore if the orderly shutdown has worked.
Go point, thanks very much. I'll give it a go.
Jon Skeet [C# MVP] - 12 Dec 2004 19:40 GMT
> > You don't need to call EndInvoke for calls to Control.BeginInvoke, even
> > though you do for general BeginXXX/EndXXX calls. The WinForms team has
[quoted text clipped - 7 lines]
> somewhere, could be bogus though, that someone had tested begininvokes
> without endinvokes and discovered a leak. Oh well, c'est la via.
Yes, but that's talking about calling BeginInvoke on a delegate not a
control.
See the comments in
http://weblogs.asp.net/cbrumme/archive/2003/05/06/51385.aspx

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too