Threading in C# - Article (free)

J

joe.on.threads

I've written an extensive document on threading in C#:

http://www.albahari.com/threading

It started out as a chapter in a book that I'm writing, but ended up
outgrowing the book! So I'm making it free and maintaining it in
parallel as a separate project.

Any feedback would be welcome.

I'm particularly interested in comments in regard the Wait and Pulse
section. I'm proposing a design pattern that makes Wait and Pulse as
simple to use as an AutoResetEvent (well, almost!)

Also, I've come down rather hard on synchronization contexts, I think,
fairly! But if you can convince me otherwise, a u-turn is not out of
the question. It has to be a good argument, though!

Thanks,
Joe
 
G

Guest

Check email, I've send several ideas privately
I've written an extensive document on threading in C#:

http://www.albahari.com/threading

It started out as a chapter in a book that I'm writing, but ended up
outgrowing the book! So I'm making it free and maintaining it in
parallel as a separate project.

Any feedback would be welcome.

I'm particularly interested in comments in regard the Wait and Pulse
section. I'm proposing a design pattern that makes Wait and Pulse as
simple to use as an AutoResetEvent (well, almost!)

Also, I've come down rather hard on synchronization contexts, I think,
fairly! But if you can convince me otherwise, a u-turn is not out of
the question. It has to be a good argument, though!
--
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche
 
K

Kevin Spencer

Awesome article Joe. I have added it to my extensive collection of favorites
and plan to direct many people to it for help. It is nicely-layed-out, uses
no more than a minimum of code for examples (which aids in not confusing the
issue), and well-written.

Kudos!

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Hard work is a medication for which
there is no placebo.
 
B

Brian Gideon

Joe,

That's an excellent article. I haven't had a chance to analyze it in
detail, but overall I like the layout and it is well written.

You might at least mention Thread.BeginThreadAffinity and the
Thread.BeginCriticalRegion in the advanced section. I'd like to see a
quality discussion on these two methods. I don't think we've ever
discussed them in this forum yet.

Brian
 
J

joe.on.threads

Thanks for the support!
You might at least mention Thread.BeginThreadAffinity and the
Thread.BeginCriticalRegion in the advanced section. I'd like to see a
quality discussion on these two methods. I don't think we've ever
discussed them in this forum yet.

I'm reluctant to comment on these methods until I can find a practical
use for them (ie what problems they will solve, excluding the obscure
or contrived). If BeginCriticalRegion prevented a section of code from
being aborted it would definitely be useful. But this is not the case,
at least in the standard CLR hosting environment. Under the SQL CLR
host, the rules are different, but then again a SQL CLR method is
unlikely to *need* thread affinity, nor to be executing critical code,
especially given the restrictions of the recommended safe permission
set.

Has anyone had any experience with BeginThreadAffinity or
BeginCriticalRegion?

Regards
Joe
 
W

Willy Denoyette [MVP]

| Thanks for the support!
|
| > You might at least mention Thread.BeginThreadAffinity and the
| > Thread.BeginCriticalRegion in the advanced section. I'd like to see a
| > quality discussion on these two methods. I don't think we've ever
| > discussed them in this forum yet.
|
| I'm reluctant to comment on these methods until I can find a practical
| use for them (ie what problems they will solve, excluding the obscure
| or contrived). If BeginCriticalRegion prevented a section of code from
| being aborted it would definitely be useful. But this is not the case,
| at least in the standard CLR hosting environment. Under the SQL CLR
| host, the rules are different, but then again a SQL CLR method is
| unlikely to *need* thread affinity, nor to be executing critical code,
| especially given the restrictions of the recommended safe permission
| set.
|
| Has anyone had any experience with BeginThreadAffinity or
| BeginCriticalRegion?
|
| Regards
| Joe
|

While they sure relate to sophisticated hosts like SQL2005, these API's have
little to do with safe or unsafe SQL2005 permissions sets.
Say you have a managed class, that implements it's own sophisticated high
performing locking primitive (for instance a spinlock) instead of using one
of the primitives offered by the framework (who are calling these API's
appropriately) , well, such a class doesn't need unsafe SQL2005 context to
run. If you ever intend to use this class in a SQL2005 hosted application,
you'll have to inform the CLR that you are holding a managed lock (a shared
state) by calling BeginCriticalRegion, so that on his turn notifies the host
that it's unsafe to escalate a thread abort (or other asynchronous
exception) to a rude abort or rude AD unload, as long as the lock is held.
The same goes for BeginThreadAffinity, whenever you hold into shared state
that consists of thread affinitized types, you need to make sure that the
host gets informed. That way the host (say SQL2005) can take measures to
return on the same thread as when the host was entered.

Willy.
 
B

Brian Gideon

Thanks for the support!


I'm reluctant to comment on these methods until I can find a practical
use for them (ie what problems they will solve, excluding the obscure
or contrived).

I appreciate your reluctance. These methods are very specialized and
would have little benefit to most developers. But, it might be
beneficial to at least discourage their use. Some inexperienced
developer who discovers threading for the first time may feel the urge
to use them just because they look cool.
If BeginCriticalRegion prevented a section of code from
being aborted it would definitely be useful. But this is not the case,
at least in the standard CLR hosting environment. Under the SQL CLR
host, the rules are different, but then again a SQL CLR method is
unlikely to *need* thread affinity, nor to be executing critical code,
especially given the restrictions of the recommended safe permission
set.

Has anyone had any experience with BeginThreadAffinity or
BeginCriticalRegion?

I have no experience. To be honest I don't fully understand how they
work. Though, I do know that the Hashtable in 2.0 uses
Thread.BeginCriticalRegion. An interesting blog on the reasoning can
be found with the following link.

<http://blogs.msdn.com/bclteam/archive/2005/06/14/429181.aspx>
 
M

Martin Carpella

Any feedback would be welcome.

Hello,

I am currently reading your article and I think it is very interesting
and extremely well written.

I however now have a question about section 3, especially your claim
that one MUST call EndInvoke() when using delegates with BeginInvoke().

I now re-read the MSDN section "Asynchronous Programming Using
Delegates" several times concerning BeginInvoke() but I cannot find an
evidence that I MUST call EndInvoke(). In fact, I have some applications
that never do so, they just use the BeginInvoke() method for a
"Fire-and-Forget" call.

Did I really introduce a resource-leek here?

Best regards,
Martin
 
W

Willy Denoyette [MVP]

| (e-mail address removed) writes:
|
| > Any feedback would be welcome.
|
| Hello,
|
| I am currently reading your article and I think it is very interesting
| and extremely well written.
|
| I however now have a question about section 3, especially your claim
| that one MUST call EndInvoke() when using delegates with BeginInvoke().
|
| I now re-read the MSDN section "Asynchronous Programming Using
| Delegates" several times concerning BeginInvoke() but I cannot find an
| evidence that I MUST call EndInvoke(). In fact, I have some applications
| that never do so, they just use the BeginInvoke() method for a
| "Fire-and-Forget" call.
|
| Did I really introduce a resource-leek here?
|
| Best regards,
| Martin


From: http://msdn2.microsoft.com/en-us/library/2e08f6yc.aspx
...
Important
Always call EndInvoke to complete your asynchronous call.


...

Willy.
 
C

Chris Nahr

Hmm, I see, I just looked up BeginInvoke() on the MSDN associated with
VS2005, should be mentioned there as well.

Ok, I'll be going code-fixing then...

There's one exception: you don't need EndInvoke for a
Control.BeginInvoke call because that's implemented differently (as a
Win32 PostMessage call).
 
H

Helge Jensen

Martin said:
Ok, I'll be going code-fixing then...

The callback is an *excellent* place to run EndInvoke :)

foo.BeginInvoke(args...,
delegate(IAsyncResult r) { foo.EndInvoke(r, args...); },
null);

Remember, if "foo" throws you have to decide what to do with the
exception when you EndInvoke.
 
M

Martin Carpella

Chris Nahr said:
There's one exception: you don't need EndInvoke for a
Control.BeginInvoke call because that's implemented differently (as a
Win32 PostMessage call).

Thanks, I found this difference on the web and I almost supposed it as
there is no possibility to add a callback in Control.BeginInvoke().

Unfortunately this won't save me from fixing up the existing code, as
most of it is part of a service logic which just uses the BeginInvoke()
for a typesafe implementation of a BackgroundWorker.

Thanks anyway & best regards,
Martin
 
M

Martin Carpella

Helge Jensen said:
The callback is an *excellent* place to run EndInvoke :)

Yes, I know, but I didn't want to write one for every "fire&forget" call
;)
foo.BeginInvoke(args...,
delegate(IAsyncResult r) { foo.EndInvoke(r, args...); },
null);

Using anonymous methods here is a nice idea, never thought of this one.
Too bad one cannot write a general handler for any delegate to be
BeginInvoke()d and EndInvoke()d, as one needs to know the exact type of
the delegate for doing this.
Remember, if "foo" throws you have to decide what to do with the
exception when you EndInvoke.

Of course. Even if I sometimes swear at it, the new behavior of
aborting on unhandled exceptions even on background threads is much
cleaner than the previous behavior in 1.x.

Best regards,
Martin
 

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