1

I use a pattern including tasks in C# where I do

Task.Factory.StartNew( .something... )
            .ContinueWith(t=> {
                                 try{ t.Wait() }
                                 catch(Exception ex) ...
                               });

if something forexample includes WCF code or other exception throwing stuff. That way Im sure that the tasks have been waited for I dont get those finalizer exceptions and I can consistently log error messages.

Recently I have seen that t.Wait() throws ObjectDisposed exception. Is my pattern wrong or should I keep the continue with only on TaskContinuationOptions.NotOnRanToCompletion.

svrist
  • 7,042
  • 7
  • 44
  • 67

2 Answers2

3

If the continuation is firing, it is pretty obvious that it has completed (one way or another); there is no need to Wait() on something that has finished. Just check how it finished (completion, cancellation (.IsCanceled), exception (.IsFaulted)), and access the result (.Result) if appropriate.

The ObjectDisposedException sounds like the notorious WCF "feature", where-by the Dispose() in WCF can throw the above (which is annoying). There are various ways proposed to wrap WCF to handle this, but this is unrelated to the task API. WCF thus swallows the actual error, and surfaces ObjectDisposedException. There are several stackoverflow questions that address this.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • So you are saying that if I just access t.Exception I can avoid the finalizer exception – svrist Nov 18 '11 at 08:54
  • "A Task's exception(s) were not observed either by Waiting on the Task " like described here: http://stackoverflow.com/questions/7883052/a-tasks-exceptions-were-not-observed-either-by-waiting-on-the-task-or-accessi – svrist Nov 18 '11 at 08:55
  • 1
    @svrist and the end of that message is "or accessing its Exception property"; so yes - checking the exception **does** mark it observed (I've just verified this in a console exe, too) – Marc Gravell Nov 18 '11 at 09:20
1

You can use the following TaskContinuationOptions to see how your Task finished.

var t = Task.Factory.StartNew(...)
(....)
 t.ContinueWith(task => (..Ran to Completion.. + task.Result),   TaskContinuationOptions.OnlyOnRanToCompletion);    
t.ContinueWith(task => (..Handle Exception .. + task.Exception),
       TaskContinuationOptions.OnlyOnFaulted);
t.ContinueWith(task => (.. Was cancelled..),
       TaskContinuationOptions.OnlyOnCanceled);
svrist
  • 7,042
  • 7
  • 44
  • 67
Alex
  • 7,901
  • 1
  • 41
  • 56