<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.claritycon.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Antuan Kinnard</title><link>http://blogs.claritycon.com/blogs/antuan_kinnard/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Mutex and Semaphore WaitHandles: An Overview</title><link>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/05/29/808.aspx</link><pubDate>Tue, 30 May 2006 01:00:00 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:808</guid><dc:creator>akinnard</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.claritycon.com/blogs/antuan_kinnard/rsscomments.aspx?PostID=808</wfw:commentRss><comments>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/05/29/808.aspx#comments</comments><description>&lt;p&gt;
I am willing to bet that every developer has been warned about the
dangers of developing multi-threaded operations at some point in their
career. Let's face it, we have enough to worry about with apps behaving
oddly as a result of client machine setup, network configuration, and
authorization changes than to let the complexities of threading be
added to the list. It's not that it’s such a difficult subject to
grasp, but there is plenty to understand in order to create a successful
robust implementation. As we all know, the biggest reasons that many
will advise careful consideration are well-founded because of its
unpredictable nature. Among other issues - like recovering from errors -
the complexity of operations happening at the same time is not always
very appealing to the developer. You need a way to 'synchronize'
threads so that one is not stepping on the other's toes. One attractive
way to tackle this problem is the use of waithandles.
&lt;/p&gt;

&lt;p&gt;The WaitHandle class is located in the System.Threading namespace.
Waithandles allow you to manage when, how, and how long a thread
will block and wait for access to a piece of functionality. This is
done by signaling (or notifying for you Java coders) another thread
when the current thread is done. The WaitHandle waits to be signaled
when one of the static wait methods - WaitOne(), WaitAny(), or
WaitAll() - is called. The WaitOne() method will block all other
threads until it is signals them to continue. Along with the timeout
parameter, the WaitAll and WaitAny
methods take WaitHandle
arguments that are used to signal and unblock any waiting threads.
Until the waiting threads are signaled (or the
timeout is reached), the threads will wait. If you’re developing a
process which requires simultaneous access to some shared resource,
your implementation should begin with determining how shared the
resource should be. When this is done, you can explore a couple more
options.
&lt;/p&gt;

&lt;strong&gt;Derived WaitHandles: Mutexes and Semaphores&lt;/strong&gt;

&lt;p&gt;The Mutex and Semaphore classes are derived from the WaitHandle
class. With extra functionality than WaitHandle, they can give you a
more scalable solution. Unlike &lt;a href="http://en.wikipedia.org/wiki/Monitor_%28synchronization%29"&gt;Monitors&lt;/a&gt;,
these waithandles can be named and accessed across the operating
system. Using the OpenExisting()
methods, you can access the specified named mutex or semaphore. I like
that along with these waithandles, you also get access control security
to implement when using it across application domains. You control
security by using .NET 2.0's new SetAccessControl() method and the
SemphoreSecurity and MutexSecurity classes. Take a look through
Microsoft’s documentation on these classes for more information.
&lt;/p&gt;

&lt;p&gt;As descendants of the WaitHandle class, mutexes and semaphores
signal the blocking thread for synchronization using the ReleaseMutex()
and Release() methods, respectively. The first thread entering the code
‘locks’ the functionality with a simple call to the WaitOne() method.
So what’s the difference between the two, you ask? The answer is that
semaphores can count. When the WaitOne()
method is called on multiple threads using the same mutex, only the
first thread to call the method will continue on while the other
threads wait for it to signal that it’s done. Once it’s done, the next
one will gain access and the rest will remain blocked, and so on down
the line. On the other hand, when the WaitOne() method is
called using a semaphore, it will not cause any other thread to be
blocked until a zero count is reached. You declare the max count with
the call to the constructor. So each time the WaitOne() method is
called, the semaphore count decrements by one until 0 is reached. Any
other thread blocking at the WaitOne()
line will enter the semaphore as the count increases. Depending on your
implementation, semaphores can give you even more flexibility and
scalability. And what architect wouldn't want that?
&lt;/p&gt;

&lt;p&gt;Let’s take a look at a couple of examples of how mutexes and semaphores lock:&lt;/p&gt;

&lt;div&gt;
&lt;p&gt;&lt;strong&gt;Mutex Example&lt;/strong&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; System;&lt;br&gt;
using&lt;/span&gt;&lt;span&gt;
System.Threading;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;namespace&lt;/span&gt;&lt;span&gt;
MutexExample {&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; &lt;span&gt;MutexTest&lt;/span&gt; {&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;private&lt;/span&gt; &lt;span&gt;const&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; MAX = 5;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;Mutex&lt;/span&gt; _mutex;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;int&lt;/span&gt; _count = 0;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Run() {&lt;br&gt; 
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_mutex = &lt;span&gt;new&lt;/span&gt;
&lt;span&gt;Mutex&lt;/span&gt;();&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;
(&lt;span&gt;int&lt;/span&gt; i = 0; i &amp;lt; MAX + 2; i++) {&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Thread&lt;/span&gt;
t = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;Thread&lt;/span&gt;(&lt;span&gt;new&lt;/span&gt; &lt;span&gt;ThreadStart&lt;/span&gt;(Start));&lt;o:p&gt;&lt;br&gt;
&lt;/o:p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.Start();&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;void&lt;/span&gt; Start() {&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;
name = &lt;span&gt;"Thread "&lt;/span&gt; + _count++;&lt;br&gt;
&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_mutex.WaitOne();&lt;br&gt;
&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Console&lt;/span&gt;.WriteLine(&lt;span&gt;"{0} : Entering mutex"&lt;/span&gt;, name);&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Thread&lt;/span&gt;.Sleep(3000);&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Console&lt;/span&gt;.WriteLine(&lt;span&gt;"{0} : Exiting mutex"&lt;/span&gt;, name);&lt;br&gt;
&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_mutex.ReleaseMutex();&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
}&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;img src="http://employees.claritycon.com/akinnard/WaitHandles/MutexExampleOutput.JPG"&gt;
&lt;/p&gt;

&lt;div&gt;
&lt;p&gt;&lt;strong&gt;Semaphore Example&lt;/strong&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;using&lt;/span&gt;&lt;span&gt; System;&lt;br&gt;
using&lt;/span&gt;&lt;span&gt;
System.Threading;&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;

&lt;p class="MsoNormal"&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;
SemaphoreExample {&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt; &lt;span&gt;SemaphoreTest&lt;/span&gt; {&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;const&lt;/span&gt; &lt;span&gt;int&lt;/span&gt; MAX =
5;&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;Semaphore&lt;/span&gt; _semaphore;&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;int&lt;/span&gt; _count = 0;&lt;o:p&gt;&lt;br&gt;
&lt;/o:p&gt;&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Run() {&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_semaphore = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;Semaphore&lt;/span&gt;(MAX,
MAX);&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;
(&lt;span&gt;int&lt;/span&gt; i = 0; i &amp;lt; MAX + 2; i++) {&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Thread&lt;/span&gt;
t = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;Thread&lt;/span&gt;(&lt;span&gt;new&lt;/span&gt; &lt;span&gt;ThreadStart&lt;/span&gt;(Start));&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;t.Start();&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;
&lt;span&gt;void&lt;/span&gt; Start() {&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_semaphore.WaitOne();&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;
name = &lt;span&gt;"Thread "&lt;/span&gt; + _count++;&lt;br&gt;
&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Console&lt;/span&gt;.WriteLine(&lt;span&gt;"{0} : Entering semaphore "&lt;/span&gt;, name);&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Thread&lt;/span&gt;.Sleep(3000);&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;Console&lt;/span&gt;.WriteLine(&lt;span&gt;"{0} : Exiting semaphore "&lt;/span&gt;, name);&lt;br&gt;
&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_semaphore.Release();&lt;span&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br&gt;
}&lt;br&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;img src="http://employees.claritycon.com/akinnard/WaitHandles/SemaphoreExampleOutput.JPG"&gt;
&lt;/p&gt;

&lt;p&gt;As you can see from these examples, mutexes and semaphores are very
simple to use. However, the same may or may not be said when actually
putting them to good use, and debugging them. If you’re anything like
me, you’re probably already thinking about 2 or 3 instances where these
WaitHandles could have helped. If you’re even more like me, you’re
probably thinking, “Why would I ever use a mutex over a semaphore.” I
would answer, “If you asked that question, you probably wouldn’t.” Most
smart developers will adhere to the ever-present goal of creating
scalable solutions where the only bounds are that of the programming
language. While this may sound facetious, the fact remains that mutexes
only allow access to one thread, while semaphores can be much more flexible.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=808" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Windows+Forms/default.aspx">Windows Forms</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Windows+Forms/default.aspx">Windows Forms</category></item><item><title>Fun with the Rebel</title><link>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/02/17/225.aspx</link><pubDate>Fri, 17 Feb 2006 21:36:00 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:225</guid><dc:creator>akinnard</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.claritycon.com/blogs/antuan_kinnard/rsscomments.aspx?PostID=225</wfw:commentRss><comments>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/02/17/225.aspx#comments</comments><description>&lt;p&gt;After almost a year of debating whether I should or shouldn't, I finally purchased my first dSLR camera - the &lt;a href="http://www.dpreview.com/reviews/canoneos350d/"&gt;Canon EOS 350D a.k.a. Digital Rebel XT&lt;/a&gt;.  I've been doing a ton of &lt;a href="http://www.dpreview.com"&gt;photography research&lt;/a&gt; and kept saying that I'd get it one day. Well, I finally
put my money where my mouth is. Turns out that putting your money where
your mouth is can be more expensive than you would think. I thought I could just purchase the camera, a lens, and some memory (256 at the most). Although you could work with this, you will most likely want to upgrade and expand your inventory soon if you're serious.&amp;nbsp; Upon purchase, I got the camera, 2 lenses, memory, and a tripod. I still needed a lens hood, polarizer, UV filter, ND filter, more memory, flash, camera bag and a few other things.&amp;nbsp; I never knew that there were so many things to buy.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;My first milestone was actually deciding on which camera. All along
I knew that the Rebel was the camera I was going to get but then I
thought I'd take a look around.&amp;nbsp; I looked at the &lt;a href="http://www.dpreview.com/reviews/nikond50/"&gt;Nikon D50&lt;/a&gt;, the &lt;a href="http://www.dpreview.com/reviews/specs/Nikon/nikon_d70s.asp"&gt;Nikon D70s&lt;/a&gt; and the &lt;a href="http://www.dpreview.com/reviews/canoneos20d/"&gt;Canon EOS 20D&lt;/a&gt;. My decision suddenly became a little more difficult as the Nikons are much cheaper than
their Canon counterparts. In the end, I chose the Rebel because 1) the
Nikons were 2 megapixels less than the Rebel (this is a big deal
because I do a fair amount of cropping) and the 20D was about $400 more
than the Rebel.&lt;/p&gt;

&lt;p&gt;One of the biggest challenges was finding a decent 'walk around'
lens. A walk around lens would allow me to take a large
range of pics without changing lenses all the time. Being new to
photography, this was a daunting task as there are so many lenses, lens
reviews and lens tests out there. And if that wasn't enough, I came
across some tests which were done incorrectly yielding incorrect
results. So to start, I came up with a list of things I had to have
without compromising image quality too much. After a few iterations, my
lens requirements simply came down to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; good image quality
&lt;/li&gt;&lt;li&gt; good performance in low light situation
&lt;/li&gt;&lt;li&gt; wide angle range
&lt;/li&gt;&lt;li&gt; decent telephoto range
&lt;/li&gt;&lt;li&gt; all-purpose (for those times when I don't wanna carry around a ton of lenses)
&lt;/li&gt;&lt;li&gt; not too expensive
&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;After all my research, I finally decided on the &lt;a href="http://the-digital-picture.com/Reviews/Canon-EF-28-135mm-f-3.5-5.6-IS-USM-Lens-Review.aspx"&gt;Canon 28-135mm f/3.5-5.6 IS USM&lt;/a&gt; and &lt;a href="http://the-digital-picture.com/Reviews/Canon-EF-50mm-f-1.8-II-Lens-Review.aspx"&gt;Canon 50mm 1.8&lt;/a&gt;
lenses. The 28-135 addresses numbers 1, 4, 5 and somewhat 6 requirements while the 50mm addresses 1, 2 and 6. Even though I haven't addressed 3 yet, I
was very successful in meeting my requirements overall.&lt;/p&gt;

&lt;p&gt;For my budget, I think I made some good decisions. Without going
into any technical details, image quality has been very good from what
I've seen so far. All of the problems I've seen so far has been user
error (go figure). In an attempt to get more comfortable with it, I took it on a
test run to the &lt;a href="http://www.chicagoautoshow.com/"&gt; 2006 Chicago Auto Show&lt;/a&gt;.
It performed really well and I actually enjoyed snapping away. Since I
obviously picked the worst day to go to the show so I wasn't able to
get too creative as I kept it on Av Mode most of the time. One of the
good things about dSLR cameras is that the images they produce can take
a good deal of punishment (without losing losing much image data) from
Photoshop, GIMP, Paint.NET, or whatever you use. Good thing too because
I didn't set the correct white balance (causing red and/or yellow
casts) and had to adjust my pics through photoshop. If I had had a
larger memory card, I could have shot in RAW format and changed the
white balance after the fact without any loss in image data. I'm not an
expert yet, but you can take a look at a few of my first Rebel pics at the Chicago Auto Show.&amp;nbsp; &lt;br&gt;&lt;/p&gt;
&lt;br&gt;
&lt;img src="http://employees.claritycon.com/akinnard/AutoShowPics/IMG_1139.jpg"&gt;
&lt;img src="http://employees.claritycon.com/akinnard/AutoShowPics/IMG_1146.jpg"&gt;
&lt;img src="http://employees.claritycon.com/akinnard/AutoShowPics/IMG_1148.jpg"&gt;
&lt;img src="http://employees.claritycon.com/akinnard/AutoShowPics/IMG_1152.jpg"&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=225" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Gadgets/default.aspx">Gadgets</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Gadgets/default.aspx">Gadgets</category></item><item><title>Sending Mail in .NET 2.0</title><link>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/01/30/186.aspx</link><pubDate>Tue, 31 Jan 2006 04:28:00 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:186</guid><dc:creator>akinnard</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.claritycon.com/blogs/antuan_kinnard/rsscomments.aspx?PostID=186</wfw:commentRss><comments>http://blogs.claritycon.com/blogs/antuan_kinnard/archive/2006/01/30/186.aspx#comments</comments><description>&lt;p&gt;I'm going to start off by admitting that it's been a while since I had
to write any code that supported sending email. Back when I was a
corporate Java/JSP developer, support for sending email was built into
almost every application's framework that we wrote. We chose email as
our 'notification service' because it was easier than writing Java code
which allowed users and developers to receive notifications any other
way. They needed a non-intrusive way to receive these notifications
which meant we couldn't install any applications. Email did just that.
Now as a (mostly) .NET developer, I haven't worked on any applications
requiring such an architecture. Regardless, I found myself playing
around with .NET's mail classes. While they are no JavaMail classes,
they've been given some attention by the Microsoft developers
in the .NET Framework version 2.0. For starters, the classes in the &lt;font face="Verdana" size="2"&gt;System.Net.Mail&lt;/font&gt; namespace - formerly &lt;font face="Verdana" size="2"&gt;System.Web.Mail&lt;/font&gt;
- are no longer wrappers for CDOSYS. They've been re-worked from the
ground up and given more functionality.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Sending email is just as simple as it's always been in the .NET
Framework. It only takes about 5 to 6 lines of code to construct a
message and send it off to the SMTP server. The object that sends the
message has been renamed from &lt;font face="Verdana" size="2"&gt;SmtpMail &lt;/font&gt;to &lt;font face="Verdana" size="2"&gt;SmtpClient &lt;/font&gt;- a more
appropriate name if you asked me. To send the message, you can use the
&lt;font face="Verdana" size="2"&gt;SmtpClient.Send&lt;/font&gt; method which has the same signature as the previous
version's. In addition to sending the message using the &lt;font face="Verdana" size="2"&gt;Send &lt;/font&gt;method, we
also have the option of sending mail asynchrounously. Using the
&lt;font face="Verdana" size="2"&gt;SmtpClient.SendAsync&lt;/font&gt; method, the application will not be blocked as it
is with the &lt;font face="Verdana" size="2"&gt;Send &lt;/font&gt;method. I'm sure some developers will see this as a
bell and/or whistle since using a separate thread would be just as
simple. However, I think it's cool to have this functionality right out
of the box. After all, aren't the bells and whistles the reasons we're all writing .NET
code? Let's look at a simple example of sending email using &lt;font face="Verdana" size="2"&gt;SendAsync&lt;/font&gt;.&lt;/p&gt;


&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.IO;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.Collections.Generic;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.Text;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.Net.Mail;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.Net.Mime;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;using&lt;/font&gt;&lt;font size="2"&gt; System.ComponentModel;&lt;/font&gt;&lt;br&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;namespace&lt;/font&gt;&lt;font size="2"&gt; SimpleMail {&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class &lt;/font&gt;&lt;font color="#008080" size="2"&gt;SimpleMail &lt;/font&gt;&lt;font size="2"&gt;{&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; private &lt;/font&gt;&lt;font color="#008080" size="2"&gt;SmtpClient&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font size="2"&gt;_smtpClient = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;null&lt;/font&gt;&lt;font size="2"&gt;;&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;

&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; public&lt;/font&gt;&lt;font size="2"&gt; SimpleMail() {&lt;br&gt;
&lt;/font&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _smtpClient = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;new &lt;/font&gt;&lt;font color="#008080" size="2"&gt;SmtpClient&lt;/font&gt;&lt;font size="2"&gt;(&lt;/font&gt;&lt;font color="#800000" size="2"&gt;"MyRelayServer.com"&lt;/font&gt;&lt;font size="2"&gt;, 25);&lt;/font&gt;&lt;br&gt;
&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;br&gt;&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; public &lt;font color="#0000ff" size="2"&gt;void&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; SendAsynchronousMail(&lt;br&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/font&gt;&lt;font size="2"&gt; toAddress,&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/font&gt;&lt;font size="2"&gt; fromAddress,&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/font&gt;&lt;font size="2"&gt; messageBody,&lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/font&gt;&lt;font size="2"&gt; subjectText,&lt;/font&gt;&lt;br&gt;&lt;font color="#008080" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; IDictionary&lt;/font&gt;&lt;font size="2"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;string&lt;/font&gt;&lt;font size="2"&gt;, &lt;/font&gt;&lt;font color="#008080" size="2"&gt;Stream&lt;/font&gt;&lt;font size="2"&gt;&amp;gt; attachmentStream,            &lt;/font&gt;&lt;br&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; string&lt;/font&gt;&lt;font size="2"&gt; token &lt;/font&gt;&lt;font color="#008000" size="2"&gt;/* UserState */&lt;/font&gt;&lt;br&gt;&lt;font size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ) {&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;

&lt;font color="#008000" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //create the message&lt;/font&gt; &lt;br&gt;
&lt;font color="#008080" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; MailMessage&lt;/font&gt;&lt;font size="2"&gt; msg = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;new &lt;/font&gt;&lt;font color="#008080" size="2"&gt;MailMessage&lt;/font&gt;&lt;font size="2"&gt;(fromAddress, toAddress); &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; msg.Body = messageBody;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; msg.Subject = subjectText;&lt;/font&gt;

&lt;br&gt;
&lt;br&gt;
&lt;font color="#008000" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //add the attachment(s)&lt;font color="#0000ff"&gt;&lt;br&gt;
&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/font&gt;&lt;font size="2"&gt; (attachmentStream != &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;null&lt;/font&gt;&lt;font size="2"&gt;) {&lt;/font&gt; &lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; foreach&lt;/font&gt;&lt;font size="2"&gt; (&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;string&lt;/font&gt;&lt;font size="2"&gt; s &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;in&lt;/font&gt;&lt;font size="2"&gt; attachmentStream.Keys) {&lt;/font&gt;
&lt;font color="#008080" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Attachment&lt;/font&gt;&lt;font size="2"&gt; attachment = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;new &lt;/font&gt;&lt;font color="#008080" size="2"&gt;Attachment&lt;/font&gt;&lt;font size="2"&gt;(attachmentStream[s], &lt;/font&gt;&lt;font color="#008080" size="2"&gt;MediaTypeNames&lt;/font&gt;&lt;font size="2"&gt;.&lt;/font&gt;&lt;font color="#008080" size="2"&gt;Application&lt;/font&gt;&lt;font size="2"&gt;.Octet);
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; attachment.Name = s.ToString();
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; msg.Attachments.Add(attachment);
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color="#008000" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //send an email to the reply address of any failures after all retries&lt;/font&gt;&lt;font size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; msg.DeliveryNotificationOptions = &lt;/font&gt;&lt;font color="#008080" size="2"&gt;DeliveryNotificationOptions&lt;/font&gt;&lt;font size="2"&gt;.OnFailure;&lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //attach the delegate to handle the callback&lt;/font&gt;&lt;font size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _smtpClient.SendCompleted += &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;new &lt;/font&gt;&lt;font color="#008080" size="2"&gt;SendCompletedEventHandler&lt;/font&gt;&lt;font size="2"&gt;(&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;this&lt;/font&gt;&lt;font size="2"&gt;.SendCompleted);&lt;/font&gt;&lt;br&gt;
&lt;font color="#008000" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //send the message and return immediately&lt;/font&gt;&lt;font size="2"&gt;&lt;br&gt;
            &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _smtpClient.SendAsync(msg, token);&lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //TODO: Do not close the stream&lt;/font&gt;&lt;font size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; private &lt;font color="#0000ff" size="2"&gt;void&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; SendCompleted(&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;object&lt;/font&gt;&lt;font size="2"&gt; sender, &lt;/font&gt;&lt;font color="#008080" size="2"&gt;AsyncCompletedEventArgs&lt;/font&gt;&lt;font size="2"&gt; e) {&lt;/font&gt;

&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/font&gt;&lt;font size="2"&gt; (e.Cancelled)      &lt;/font&gt;
&lt;font color="#008080" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/font&gt;&lt;font size="2"&gt;.WriteLine(&lt;/font&gt;&lt;font color="#800000" size="2"&gt;"The message [{0}] was canceled."&lt;/font&gt;&lt;font size="2"&gt;, e.UserState.ToString());&lt;/font&gt;

&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/font&gt;&lt;font size="2"&gt; (e.Error != &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;null&lt;/font&gt;&lt;font size="2"&gt;) {&lt;/font&gt;
&lt;br&gt;
&lt;font color="#008080" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; StringBuilder&lt;/font&gt;&lt;font size="2"&gt; errorMsg = &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;new &lt;/font&gt;&lt;font color="#008080" size="2"&gt;StringBuilder&lt;/font&gt;&lt;font size="2"&gt;();
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; errorMsg.Append(&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;string&lt;/font&gt;&lt;font size="2"&gt;.Format(&lt;/font&gt;&lt;font color="#800000" size="2"&gt;"An error occurred sending message [{0}].  {1}"&lt;/font&gt;&lt;font size="2"&gt;, e.UserState.ToString(), e.Error.Message));&lt;/font&gt;

&lt;br&gt;
&lt;font color="#0000ff" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if&lt;/font&gt;&lt;font size="2"&gt; (e.Error.InnerException != &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;null&lt;/font&gt;&lt;font size="2"&gt;)
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; errorMsg.Append(&lt;/font&gt;&lt;font color="#008080" size="2"&gt;Environment&lt;/font&gt;&lt;font size="2"&gt;.NewLine + &lt;/font&gt;&lt;font color="#800000" size="2"&gt;"Inner exception message: "&lt;/font&gt;&lt;font size="2"&gt; + &lt;/font&gt;&lt;font size="2"&gt;e.Error.InnerException.Message);&lt;br&gt;
&lt;/font&gt;&lt;font color="#008080" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/font&gt;&lt;font size="2"&gt;.WriteLine(errorMsg);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;else &lt;/font&gt;&lt;font size="2"&gt;{&lt;/font&gt;&lt;font color="#008080" size="2"&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console&lt;/font&gt;&lt;font size="2"&gt;.WriteLine(&lt;/font&gt;&lt;font color="#800000" size="2"&gt;"Message [{0}] sent."&lt;/font&gt;&lt;font size="2"&gt;, e.UserState.ToString());
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; public &lt;font color="#0000ff" size="2"&gt;void&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; CancelMail() {
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _smtpClient.SendAsyncCancel();
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;br&gt;
}&lt;/font&gt;&lt;br&gt;
&lt;p&gt;As
you'd expect, an event handler has been added for the callback as well
as an identifier, or token, for the message sent.
&lt;font face="Verdana" size="2"&gt;SendCompletedEventhandler &lt;/font&gt;sends the &lt;font face="Verdana" size="2"&gt;AsyncCompletedEventArgs &lt;/font&gt;object to
the &lt;font face="Verdana" size="2"&gt;SendCompleted &lt;/font&gt;callback method. As shown in the example code, you
can use &lt;font face="Verdana" size="2"&gt;AsyncCompletedEventArgs &lt;/font&gt;to determine if an error occurred while
sending and if the message was canceled. The &lt;font face="Verdana" size="2"&gt;UserState&lt;/font&gt; property will be populated with the token object that was passed to the &lt;font face="Verdana" size="2"&gt;SendAsync &lt;/font&gt;method.  &lt;/p&gt;

&lt;p&gt;Along with the &lt;font face="Verdana" size="2"&gt;SendAsync &lt;/font&gt;method comes the &lt;font face="Verdana" size="2"&gt;SendAsyncCancel
&lt;/font&gt;method. Can anyone guess what this does? That's right, cancels the
message. However, don't expect it to cancel a message that the server
has already queued. Once it's there, you won't be able to use the &lt;font face="Verdana" size="2"&gt;SendAsyncCancel &lt;/font&gt;method to remove it from the SMTP queue.  &lt;/p&gt;

&lt;p&gt;Another change worth mentioning is more options for sending
attachments. With the 2.0 version of the framework, developers now have
the option of sending attachments directly from a stream. So you no
longer need a file to send from because anything from a &lt;font face="Verdana" size="2"&gt;MemoryStream &lt;/font&gt;to a &lt;font face="Verdana" size="2"&gt;CryptoStream &lt;/font&gt;can be sent directly from the stream itself.  Be sure if you're using a stream with the &lt;font face="Verdana" size="2"&gt;SendAsync
&lt;/font&gt;method that you don't close the stream before the send operation is
done sending the message to the server. This will cause an &lt;font face="Verdana" size="2"&gt;SmtpException&lt;/font&gt;
exception since the method is not actually done with the stream. This leads me to my next point: When checking exceptions
thrown by these classes, be sure to check the inner exception. I'm sure
I don't need to tell anyone this because we all check our inner
exceptions. &lt;i&gt;*cough*&lt;/i&gt; This is an invaluable tip for anyone using this
namespace. In the case of prematurely closing memory streams that is being sent as an attachment,
the first exception in the chain is an &lt;font face="Verdana" size="2"&gt;SmtpException
&lt;/font&gt;with the message, "Failure sending mail." Not very informative to those
of us without psychic abilities, eh? Checking the inner exception will
yield a &lt;b&gt; &lt;/b&gt;&lt;font face="Verdana" size="2"&gt;NotSupportedException &lt;/font&gt;exception and the message, "Stream does not support reading."&amp;nbsp; So check and log those inner exceptions!  &lt;/p&gt;

&lt;p&gt;Now for the all-important question, "How do I receive email?"  Short answer is that you can't receive email using the &lt;font face="Verdana" size="2"&gt;System.Net.Mail
&lt;/font&gt;namespace. This is one area I think JavaMail has got .NET beat. That said,
if you're up for the challenge you can write your own communication
with your POP and IMAP store using sockets. If you're not up to this
challenge, there are a number of components written that can save you
some time &lt;a href="http://www.asp.net/ControlGallery/default.aspx?Category=37&amp;amp;tabindex=2"&gt;here&lt;/a&gt; and &lt;a href="http://dotnet.devdirect.com/ALL/InternetComponents_SGROUP_0003.aspx"&gt;here&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;There's a lot more functionality in the &lt;font face="Verdana" size="2"&gt;System.Net.Mail&lt;/font&gt;namespace
that should be explored. Sending email through SSL, sending
alternate ways to view the message, and delivery notifications are a
few more areas worth taking a look at.&amp;nbsp; To help get you started, you can check out Dave Wanta's
site at &lt;a href="http://systemnetmail.com"&gt;http://systemnetmail.com&lt;/a&gt;.&amp;nbsp; This is a pretty good FAQ about the
namespace.&amp;nbsp; If you'd like a comparison with the .NET 1.1,
check out &lt;a href="http://systemwebmail.com"&gt;http://systemwebmail.com&lt;/a&gt;.&lt;br&gt;
 &lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=186" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Windows+Forms/default.aspx">Windows Forms</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.claritycon.com/blogs/antuan_kinnard/archive/tags/Windows+Forms/default.aspx">Windows Forms</category></item></channel></rss>