tags:

views:

155

answers:

2

I am currently replacing some home baked task functionality with a new implementation using the new System.Threading.Tasks functionality found in .net 4.

I have a slight issue though, and although I can think of some solutions I would like some advice on which is generally the best way to do it, and if I am missing a trick somewhere.

What I need is for an arbitrary process to be able to start a Task but then carry on and not wait for the Task to finish. Not a problem, but when I then need to do something with the result of a task i'm not quite sure the best way of doing it.

All the examples I have seen use either Wait() on the task until it completes or references the Result parameter on the task. Both of these will block the thread which started the Task, which I don't want.

Some solutions I have thought of:

  1. Create a new thread and start the task on that, then use Wait() or .Result to block the new thread and sync the result back to the caller somehow, possibly with polling to the tasks IsCompleted parameter.

  2. Have a 'Notify Completed' task which I can start after completion of the task I want to run which then raises a static event or something.

  3. Pass a delegate into the input of the task and call that to notify that the task is finished.

I can think or pros and cons to all of them, but I especially don't like the idea of having to explicitly create a new thread to start the task on when the one of the aims of using the Task class in the first place is to abstract away from direct Thread usage.

Any thoughts about the best way? Am I missing something simple? Would a 'Completed' event be too much to ask for :)? (Sure there is a good reason why there isn't one!)

+1  A: 

I suspect you're looking for Task.ContinueWith (or Task<T>.ContinueWith). These basically say, "When you've finished this task, execute this action." However, there are various options you can specify to take more control over it.

MSDN goes into a lot more detail on this in "How to: Chain Multiple Tasks With Continuations" and "Continuation Tasks".

Jon Skeet
Yes I understand that, but it doesn't solve the problem of knowing when the sequence of Tasks has finished without calling Task.Wait() (and hence blocking) on the thread that started the task.One approach I thought of (as above) was to use Task.ContinueWith to chain a task which raises an event which interested parties can subscribe to. This will keep the original task atomic.
Ben Williams
@bwilliams: Why not just expose the task, and interested parties can call `Task.ContinueWith`? I don't see in what way it *doesn't* solve the problem of knowing when the task has completed... it's a non-blocking call that says, "Call me back when this is finished."
Jon Skeet
(Or instead of exposing the task itself, you can provide your own method which then just calls `ContinueWith` internally. It's the same thing, really.)
Jon Skeet
Sorry, you are completely right. I originally read all the stuff on MSDN, including all the links you posted but for some reason I read Task.ContinueWith as taking another Task as a parameter for execution after the initial tasks completion, not a simple Action or Func. Thanks alot, although I feel stupid now :)
Ben Williams
@Ben Williams: Don't worry - it can get pretty confusing :)
Jon Skeet
A: 

You can apply a task continuation.

Alternatively, Task implements IAsyncResult, so you can use the standard approaches for that interface (blocking, polling, or waiting on its WaitHandle).

Stephen Cleary
For the task continuation topic please see my comment under Jon Skeet's post.Blocking and polling I don't like the idea of as it will mean having to start another thread to keep the original thread that started the task responsive.I did see I could use WaitHandle, but the documentation says the preferred way is to use Task.Wait(). That said, as that doesn't do what I want maybe the WaitHandle is the best for me
Ben Williams