Information Technology Reference
In-Depth Information
encounters any other kind of exception, it looks into the dictionary. If a
handler Action<> has been registered, it calls that handler. If not, then it
returns false immediately, having found an exception that it should not be
handled.
Yo u m a y b e w o n d e r i n g w h y t h e o r i g i n a l A g g r e g a t e E x c e p t i o n g e t s t h r o w n
rather than the single exception for which there was no handler. The prob-
lem is that throwing one exception out of the collection could lose impor-
tant information. The InnerExceptions may contain any number of
exceptions. More than one may be of a type that is not expected. You must
return the entire collection or risk losing much of that information. In
many cases, there will be only one exception in the AggregateException's
InnerExceptions collection. However, you should not code that way
because when you do need that extra information, it won't be there.
Of course, this feels a bit ugly. Wouldn't it be better to prevent the excep-
tion from leaving the task doing the background work? In almost all cases,
that is better. That requires changing the code that runs the background
task to ensure that no exceptions can exit the background task. Whenever
you use the TaskCompletionSource<> class, that means never calling
Tr y S e t E x c e p t i o n ( ) , b u t r a t h e r e n s u r i n g t h a t e v e r y t a s k s o m e h o w c a l l s
Tr y S e t R e s u l t ( ) t o i n d i c a t e c o m p l e t e n e s s . T h a t w o u l d m e a n t h e f o l l o w i n g
changes to startDownload. But, just like I said earlier, you should not be
catching every single exception. You should catch only those exceptions
from which you can recover. In this example, you can reasonably recover
from a WebException, indicating that the remote host isn't available. Other
exception types would indicate more serious problems. Those should con-
tinue to generate exceptions and stop all processing. That causes the fol-
lowing changes to the startDownload method:
private static Task < byte []> startDownload( string url)
{
var tcs = new TaskCompletionSource < byte []>(url);
var wc = new WebClient ();
wc.DownloadDataCompleted += (sender, e) =>
{
if (e.UserState == tcs)
{
if (e.Cancelled)
tcs.TrySetCanceled();
else if (e.Error != null )
 
Search WWH ::




Custom Search