TT (Tom Tempelaere) <"TT \(Tom Tempelaere\)" <_|\|_0§P@|/
\|titi____AThotmail.com|/\|@P§0_|\|_> said:
That is just one aspect of threading. For instance you would like to be
notified of thread completion automatically (coded as an event in my
threading class). You would like an easy way to pass parameters to the
thread, just construct the class with the appropriate parameters.
You can do that using delegates too.
You woul like other console output for exceptions in threads (eg unhandled exception
handler, status output, debugging etcetc), write a launching handler with a
surrounding try-catch and output the way you want (this handler is also
necessary for firing the thread completion event), or handle any way you
want automatically.
Again, you can do that with a delegate. There's nothing to say you have
to pass the delegate you're given straight to the Thread constructor.
You would like a clean way to seperate thread execution
from thread cleanup for instance (automated of course), and have a clear
indication of how your thread should shutdown gracefully.
Ditto. Supply one delegate for cleanup and one for execution, then
execute one followed by the other.
This last one is
an overridable cancel method. The implemeter of the thread knows how your
thread can shut down gracefully so supplies implementation to do so. You
would like your thread behaviour to be encapsulated in a clean way. The
thread internals are protected (override) and private, and automated. The
public interface consists of threading functionality (start, abort, cancel,
joining, etc) and the things you want to be public (events ...).
Again, that could be abstracted in a way that a delegate could use - it
could take the object to query for when it should be cancelled, etc.
Actually in my current threading lib I've gone one step further and added
the abstraction of seperating the thread and that what is executing on it.
That results in a task base class, and a thread class that can execute
tasks. I implemented task completion using WaitHandle (ManualResetEvent, set
when completed) so other threads/tasks can wait for them to finish. In my
current project I need to wait for several tasks to finish in one main
kernel thread, so I collect the task completion handles and wait for them
using WaitHandle.WaitAll. Easy writing.
Again, I see nothing to stop you from specifying the actual method to
execute using a ThreadStart delegate rather than using inheritance
though.
I completely agree. But in this case I think it is a good way to do so. I
have no objection against the fact that .NET made the Thread class sealed.
But my way of coding threads is elegant and automated. What do I need
more?
Well, it prevents you from simply running a method in an existing class
which already derives from something else in a different thread (with
your added functionality), for a start. Using a delegate, you'd get all
the benefits of your base class etc but without needing to adjust the
natural class hierarchy just for the purpose of threading.
In my view, a delegate specifies exactly "something to run" - the whole
concept fits threading perfectly. Why not use it, rather than
inheritence?
It all depends on what level you are programming I guess.
Not sure what you mean by that.
Not a _class_ but a _progam_. Basically a kernel for an industrial printer
which has to be multi-threaded because things need to execute in parallel
and be synchronized. No UI inside (of course), although a UI component can
plug in to monitor
.
I was asking about your base class, but I think you've explained a lot
of it above anyway.
I am using them, of course. Where did I say I didn't?
Well, you said the interface remains the same. That means that if
you're using Java, you're not using C#'s events or delegates, for
instance. If you restrict your interface to the intersection of what
all the languages you're interested in support, you're bound to end up
with a less idiomatic interface.
Actually I like my pattern but I don't see it reflected in any language. It
comes natural to me and obviously unnatural to others. Perhaps it is just a
matter of taste.
Probably. I'm afraid I still don't like it.
--
Jon Skeet - <
[email protected]>
Jon, you can take this to an extreme, and just start coding C again.
Anything can be coded without classes and derivation or interface
inheritance (well, not really because .NET doesn't allow, but that's not the
point). Your call. I prefer OO if it suits and fits what I need to do. And
in this case I've proven for myself (at the very least) that this is the way
to go. But seems like this is not true for others, so in the end everyone
does things that suits him best. In all my threading apps I've been very
happy that I introduced these. There is no hard proof, just experience I
guess. I don't even know why Java threads made you fear thread-derivable
classes. I see only benefits in my approach, and no disadvantages up to this
point. I'm using the pattern for years now. So I'll stick to what I do for
several years with success now.
Your objections are rather thin. Anything can be done in another way; and I
think the alternative approach you suggest results in more code, and less
readable code because in each developer does things his way. The overridable
interface will remain the same for all thread-derivable classes, so no
differences in naming in each thread app because you can't just rename
overridables. A clear pattern that is the same in every app. That is what I
like to see in apps because they are easily reviewed. Everybody in the
company should stick to the pattern so that interchangeability of code
increases. I see every other guy coding threads in a different way and in
the company I work for for instance, I would like them to code threading all
in the same way. The same is true for other domains such as db access and
automisation, UI automisation, etc etc. Sure .NET has a nice library that
(nearly) does it all, but programmers styles differ too much, plus you see
programmers re-coding the same things over and over. I really hate this.
The fact that you have to derive from the base thread class is not bad,
because it should be the only thing it derives from. If you would want to
derive from more than one base class, then your design is obviously wrong. I
wouldn't even dare letting it implement an interface, because that is not
the intention when you derive from the thread. The thread encapsulates
everything that is on the thread, what is needed for the thread to start and
stop gracefully, what is run on the thread etc. It is the controller of what
executes on the thread, and that is a private matter (although the
overridables are protected - in C++ these can be private which is even
better for such patterns). And there is nothing else that such a thread
class should do. You will also want to seal the derived class directly
unless your design says otherwise. I seal by default unless my design says
otherwise.
I am not advocating the introduction of such a class in the .NET library.
The library fits my view of threads and how to make them maintainable. Each
threading app will use the same interface (the english word) of the library
and so all thread apps look the same. In my case they even look the same in
C++. Perfect. All thread main entry's have the same name and signature. All
thread canceling methods have the same name, the same signature. Thread
cleanup methods all have the same name. Ok, the event I used in C# is
different than what I did in C++, but the idea is completely the same
(callback) and is very elegant in both libraries. In my point of view there
is more to a thread than simply that was is run on it.
[]
Indeed, the interface hides the way threads are written in each language.
Sometimes the outer interface may differ because of different ways of doing
things, eg events (C#) vs listeneres (Java).
There are differences in the interfaces of course. Every language has things
that differ from others. Events in c#, listeners in Java and callbacks in
C/C++ (fptr). But the underlying idea remains the same. I'm not restricting
anything, I am assuring that the interface is consistent from a language
neutral point of view. Threading is similar in all languages from a high
level point of view, it's the internals that differ.
Anyway, I gotta go party at the city parade ;-) Ghent
(
http://www.cityparade.be)
Cheers,