Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TaskCreationOptions.DenyChildAttach in .NET 4

I have seen that in .NET 4.5 that Task.Run() is the equivalent to

Task.Factory.StartNew(someAction, 
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

But in .NET 4.0, TaskCreationOptions.DenyChildAttach does not exist. Is this where TaskEx.Run comes in? A comment in this question seems to indicate that, but no elaboration is given. What is the equivalent in .NET 4.0 for .NET 4.5's Task.Run?

like image 446
Mike_G Avatar asked Sep 24 '14 13:09

Mike_G


1 Answers

The DenyChildAttach option not only doesn't exist in the TaskCreationOptions enum, it doesn't exist in the framework itself. The code that would actually deny the attempted attachment of a child task doesn't exist in .Net 4.0. (more in New TaskCreationOptions and TaskContinuationOptions in .NET 4.5).

So the exact equivalent of Task.Run doesn't and can't exist in .Net 4.0. The closest thing to it would be to simply not use the AttachedToParent value in that enum:

public static Task<TResult> Run<TResult>(Func<TResult> function)
{
    return Task.Factory.StartNew(
        function, 
        CancellationToken.None, 
        TaskCreationOptions.None, 
        TaskScheduler.Default);
}

A more important difference IMO is the support for async delegates in Task.Run. If you pass an async delegate (i.e. Func<Task<TResult>>) to Factory.StartNew you get back in return Task<Task<TResult>> instead of Task<TResult> as some would expect which is a source of many headaches. The solution to that is to use the TaskExtensions.Unwrap extension method that "Creates a proxy Task that represents the asynchronous operation of a Task<Task<T>>":

public static Task<TResult> Run<TResult>(Func<Task<TResult>> function)
{
    return Task.Factory.StartNew(
        function, 
        CancellationToken.None, 
        TaskCreationOptions.None, 
        TaskScheduler.Default).Unwrap();
}
like image 99
i3arnon Avatar answered Sep 21 '22 13:09

i3arnon