Assume the following synchronous code:
try
{
Foo();
Bar();
Fubar();
Console.WriteLine(\"All done\");
}
catch(Exception e) // For illustration
Now, I haven't really used the TPL much, so this is just a stab in the dark. And given what @Servy mentioned, perhaps this won't run completely asynchronously. But I figured I'd post it and if it's way off the mark, you can downvote me to oblivion or I can have it deleted (or we can just fix what needs fixing)
public void RunAsync(Action onComplete, Action errorHandler, params Action[] actions)
{
if (actions.Length == 0)
{
//what to do when no actions/tasks provided?
onComplete();
return;
}
List tasks = new List(actions.Length);
foreach(var action in actions)
{
Task task = new Task(action);
task.ContinueWith(t => errorHandler(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
tasks.Add(task);
}
//last task calls onComplete
tasks[actions.Length - 1].ContinueWith(t => onComplete(), TaskContinuationOptions.OnlyOnRanToCompletion);
//wire all tasks to execute the next one, except of course, the last task
for (int i = 0; i <= actions.Length - 2; i++)
{
var nextTask = tasks[i + 1];
tasks[i].ContinueWith(t => nextTask.Start(), TaskContinuationOptions.OnlyOnRanToCompletion);
}
tasks[0].Start();
}
And it would have usage like:
RunAsync(() => Console.WriteLine("All done"),
ex => Console.WriteLine(ex),
Foo,
Bar,
Fubar);
Thoughts? Downvotes? :)
(I definitely prefer async/await though)
EDIT: Based on your comments to take Func, would this be a proper implementation?
public void RunAsync(Action onComplete, Action errorHandler, params Func[] actions)
{
if (actions.Length == 0)
{
//what to do when no actions/tasks provided?
onComplete();
return;
}
List tasks = new List(actions.Length);
foreach (var action in actions)
{
Func nextActionFunc = action;
Task task = new Task(() =>
{
var nextTask = nextActionFunc();
nextTask.ContinueWith(t => errorHandler(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
nextTask.Start();
});
tasks.Add(task);
}
//last task calls onComplete
tasks[actions.Length - 1].ContinueWith(t => onComplete(), TaskContinuationOptions.OnlyOnRanToCompletion);
//wire all tasks to execute the next one, except of course, the last task
for (int i = 0; i <= actions.Length - 2; i++)
{
var nextTask = tasks[i + 1];
tasks[i].ContinueWith(t => nextTask.Start(), TaskContinuationOptions.OnlyOnRanToCompletion);
}
tasks[0].Start();
}