Monitor, does not work when disposing...

J

jodleren

Hi

I have some components, which have a calculate thread (each). The
thread is started when needed, then I use monitor.pulse to make it go
again... it works, but when I need to shut it down (setting a
"terminate" varible for that), and call

Monitor.Enter(CalcThread.trigger);
Monitor.Pulse(CalcThread.trigger);
Monitor.Exit(CalcThread.trigger);


Then it does not trig anything..... how come?

The thread is:

public void Execute()
{
Monitor.Enter(trigger);
for (; !terminated; )
{
try
{
OpenConnection();
.... database stuff....
}
catch (Exception e)
{
object[] myArray = new object[2];
myArray[0] = this;
myArray[1] = "Thread error: " + e.Message;
host.BeginInvoke(host.passerroron, myArray);
}
finally
{
CloseConnection();
}
Monitor.Wait(trigger);
}
Monitor.Exit(trigger); // *** waits forever here....
host.BeginInvoke(host.statTerminated);
}
}
 
J

James A. Fortune

Finally, I'll point out that at least from the code you posted, it's not
clear why you are using a dedicated thread at all.  It appears that each
iteration through the loop is completely independent from any other
iteration.  If that's really the case, then it seems to me that you'd be
better off using the ThreadPool (either directly or via theTask
Parallel Library) to handle each invocation of the background work.

In the PDC08 session:

TL26 - Parallel Programming for Managed Developers with the Next
VErsion of Microsoft Visual Studio

Daniel Moth said:

"Why do we introduce a new concept called "Task" and we didn't use a
Thread? And, it's what I said earlier on. Maybe I said it too
quick[ly]. So, with the thread, at the OS level, it's both the unit
of scheduling and also the unit of partitioning. That is bad because
you want to be able to partition a lot, but you only want few
threads. So that's why we need a higher level, a higher abstraction,
a lighter unit of work. And that's why we're introducing Tasks."

It seems that using the Task Parallel Library is more natural and
would be preferable to using thread pools in most cases. In your
opinion, in what situation would using thread pools actually be better
than using the Task Parallel Library?

Thanks,

James A. Fortune
(e-mail address removed)
 
J

James A. Fortune

On 7/13/11 12:03 PM, James A. Fortune wrote:
In the PDC08 session:
TL26 - Parallel Programming for Managed Developers with the Next
VErsion of Microsoft Visual Studio
Daniel Moth said:
"Why do we introduce a new concept called "Task" and we didn't use a
Thread?  And, it's what I said earlier on.  Maybe I said it too
quick[ly].  So, with the thread, at the OS level, it's both the unit
of scheduling and also the unit of partitioning.  That is bad because
you want to be able to partition a lot, but you only want few
threads.  So that's why we need a higher level, a higher abstraction,
a lighter unit of work.  And that's why we're introducing Tasks."
It seems that using the Task Parallel Library is more natural and
would be preferable to using thread pools in most cases.  In your
opinion, in what situation would using thread pools actually be better
than using the Task Parallel Library?

It's not either or.  That's why I wrote parenthetically "either directly
or via the Task Parallel Library".  Using the static ThreadPool class
directly is "old school".  Frankly, it still works fine and for simple
things it might be the most expedient.

Your comments, as usual, are appreciated. I don't mind "force of
habit" programming styles, not even when someone uses what one
presenter called "clipboard inheritance."
But the TPL is a nicely engineered piece of the framework and very
useful.  If you have the option to use the TPL, I would recommend that.

Noting, however, that an asynchronous task created by the TPL is going
to use the same thread pool that the ThreadPool itself manages.  You are
still using the ThreadPool when you use the TPL.  It's just not quite so
obvious.  :)

There is no force keeping me from using the TPL :). The Moth PDC
session even pointed out that the Task syntax is just like the Thread
syntax. I did realize that the TPL uses a thread pool.
Note that the TPL didn't actually introduce the concept of "Task", no
matter what Moth says.  Even back in the .NET 1.1 days, the docs for the
ThreadPool used the word "task" and "work item" interchangeably, in the
sample code for example.  This is formalized in the .NET 4.0 docs, to
match up with the use of the ThreadPool by the TPL.

ThreadPool description pre-4.0: "Provides a pool of threads that can be
used to post work items, process asynchronous I/O, wait on behalf of
other threads, and process timers."  From 4.0 on: "Provides a pool of
threads that can be used to execute tasks, post work items, process
asynchronous I/O, wait on behalf of other threads, and process timers."

They just stuck "execute tasks" in there, to line up with the new
built-in usage of the ThreadPool.  But all along, a "work item" (as in
ThreadPool.QueueUserWorkItem()) has always just been another way of
saying "task", and people were using the word "task" long before the TPL
came along, even to describe the same basic thing the TPL describes as a
"task".

Your point about work items predating tasks is surprising and
interesting. Mr. Moth took pains to point out that a separate API was
created for Tasks and that optimizations such as "work stealing" or
choosing the next Task based on cache considerations were added to
Task logic. I never know how much credit I should give to MS for new
features because sometimes they take a lot of credit for a little
work, but they obviously did something. Your observation about work
items does show a certain perspicacity for noticing such a subtle re-
emphasis of an apparently innocent bystander. In some cases, MS
decides to dredge up some possibly decrepit software technology from
the depths of increasing obscurity and gentrify it back to
respectability. I think MS saw that Tasks were more flexible than
Threads and thus put more effort into the TPL. I like the way you
pointed out the change in the .NET docs. BTW, do you have a link to
those docs?

James A. Fortune
(e-mail address removed)
 
J

James A. Fortune

[...]
Your point about work items predating tasks is surprising and
interesting.  Mr. Moth took pains to point out that a separate API was
created for Tasks and that optimizations such as "work stealing" or
choosing the next Task based on cache considerations were added to
Task logic.

Note that there's no reason per se that the ThreadPool could not support
a work-stealing implementation.  Apparently it was decided to put
higher-level optimizations such as that in the TPL.

That's an interesting point. It brings up the choice of where to put
things, which you address below.
As is the case with most things in any industry, most people assume a
situation is nearer one extreme or the other than it really is.  It's
extremely rare for someone to come up with something truly
revolutionary; certainly most of the companies most people think of as
revolutionary in today's computer industries really aren't.  They simply
happened to come along with the right refinement at the right time.

Likewise, people dismiss as nothing significant innovations simply
because they are biased (happens a lot against Microsoft these days),
and/or simply don't comprehend the amount of actual work involved in
taking a spark of an idea and creating a real, practical and useful
implementation around it.

I don't know why it's down now, but if and when it comes back up (it's
been down a week or two now), Joe Duffy's blog is a good place to read
about a lot of the interesting and hard thinking that goes into
concurrency support in .NET.  You can find it here:http://www.bluebytesoftware.com/

He even has a good article about work-stealing task queues implementations.

Good advice. I have Joe Duffy's Concurrent Programming book. Similar
to the way the Design Patterns book is forcing programmers into more
flexible and maintainable designs, Concurrent Programming is causing
programmers to look at types in a different way to foster concurrency.
For what it's worth, I don't feel that the ThreadPool ever fell into
obscurity.  If anything, background tasks have become more and more
important as a programming technique over the years, and the
proliferation of multi-core CPUs has made this even more important, at
least for certain kinds of applications.

Of course, even pre-TPL we have had various ways to use the ThreadPool
without doing so explicitly.  Using the BeginInvoke() method on a
delegate instance, using the BackgroundWorker class, using the async
APIs on various i/o types (Begin/End…, …Async, etc.), these all use the
ThreadPool "under the hood".  So if the ThreadPool did fall into
obscurity, it's only because it was doing the heavy lifting for the rest
of the API, thanklessly behind the scenes.  :)

IMHO, the TPL is a natural evolution of the basic ThreadPool API.  Of
course, Microsoft did not invent these concepts on their own.
Concurrency research has been on-going for decades, and the TPL borrows
heavily from existing concepts and other implementations.  But I think
they deserve high marks for their implementation and their recognition
of that kind of API as an important development in a framework like .NET.

I don't think it's that Microsoft put more effort into the TPL per se.
It's just that as an API, the ThreadPool was already complete.  It
didn't make sense to try to stuff more things in there.  Instead, there
_needed_ to be a whole new API, where the new ways of dealing with tasks
could be put in a dispatching-implementation-agnostic way.

Note that there's no requirement that the TPL actually be implemented on
top of the ThreadPool; that just happens to be the way it is now, but it
could always change, or different kinds of thread pools could be
supported.  Had they added all those features in the ThreadPool class
itself, then that would imply that the ThreadPool would always be the
dispatching and execution mechanism for tasks, for all time.

I don't think it's a matter of whether the ThreadPool was more or less
flexible.  It's more a matter of keeping the API pure and without
unnecessary dependencies on other APIs.

I wasn't actually thinking about the ThreadPool as one of the decrepit
artifacts that got resurrected, although I see now that the order of
my sentences implied that. When I said that the Tasks are more
flexible than the ThreadPool, I was thinking that Tasks could handle
either thread or task situations, but you correctly point out that the
ThreadPool can go the other way. The API purity hypothesis is
intriguing. Do you have any other corroborating facts to nail down
that hypothesis?
It's not hard to find.  :)  Just go to the main page for the ThreadPool
class:http://msdn.microsoft.com/en-us/library/system.threading.threadpool..aspx

Oops. My bad. To me, it sounded like you got it from some kind
of .NET open source standards documentation. I'm almost finished with
the PDC 08 sessions (about eight to go). When I'm done with the PDC
09 sessions I'll start digging into MSDN a lot more since the PDC 10
sessions are nearly impossible to download. It's taking a long time
to go through the sessions, but I'm getting a much better picture of
the software technologies that MS is working on, along with a better
appreciation of the mammoth reorganization they underwent recently.
I'm almost to the point where plowing through the MSDN documentation
will crystalize my understanding.

James A. Fortune
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top