Task.Factory.StartNew() overloads

Go To StackoverFlow.com

8

I've got really simple code:

static void Main(string[] args)
{
    var task = Task.Factory.StartNew(GetInt);

    var task2 = Task.Factory.StartNew(
        () =>
        {
            return GetInt();
        });
}

static int GetInt()
{
    return 64;
}

Why do I get a compiler error for the first task? The method signatures (no params, return type is int) are equal, aren't they?

I know a solution(which is quite simple: var task = Task.Factory.StartNew<int>(GetInt);) but I'd like to know whats the problem with the code above.

2012-04-05 18:54
by GameScripting
What's the compiler error - James Wiseman 2012-04-05 18:58
Please try yourself, I only have the german compiler error text: Der Aufruf unterscheidet nicht eindeutig zwischen folgenden Methoden und Eigenschaften: "System.Threading.Tasks.TaskFactory.StartNew<int>(System.Func<int>)" und "System.Threading.Tasks.TaskFactory.StartNew(System.Action)" but it doesn't make sense cause GetInt will return int not voidGameScripting 2012-04-05 19:02


3

You get an ambiguous call error because the method signature is the same. Return values are not part of the signature.

Since you don't provide an explicit return type, the compiler doesn't know which to take.

Method Signature in C#

2012-04-05 19:01
by Alex
I think you really need to rephrase your answer: Action is very much a different type than Func. Your answer currently reads as if the StartNew implementation should not even compile - ChrisWue 2012-04-05 19:07
Noted, thank you - Alex 2012-04-05 19:09


3

Because the compiler cannot decide which of these two overloads to use:

StartNew(Action)
StartNew<TResult>(Func<TResult>)

The reason for that is that the return type is not part of the overload resolution in C# (same way as you can't have two overloads only differing in return types) and therefore the compiler cannot decide whether GetInt should be an Action or a Func<T>. Forcing to use the generic version by calling StartNew<int>(GetInt) will provide the required information.

2012-04-05 19:13
by ChrisWue
This is detfinfly the best solution - Jens Kloster 2013-10-31 12:50


2

For the record, here are two more ways of doing it (that compile):

var task3 = Task.Factory.StartNew((Func<int>)GetInt);
var task4 = Task.Factory.StartNew(() => GetInt());
2012-04-05 19:11
by Douglas


1

Would help to show the exception: "The call is ambiguous between the following methods or properties: 'System.Threading.Tasks.TaskFactory.StartNew(System.Action)' and 'System.Threading.Tasks.TaskFactory.StartNew(System.Func)'"

If you take a look there are two possible methods:

public Task<TResult> StartNew<TResult>(Func<TResult> function);
public Task StartNew(Action action);

If you add the <int> or supply a Func<int> you force it to take the first signature. Without that your code is ambiguous.

2012-04-05 19:06
by Ian Mercer


0

You get the compile error because the StartNew method takes in either an Action (returns void) or a Func (returns something) predicates with it's various overloads, and not a direct delegate.

2012-04-05 18:58
by Scorpion-Prince
That sounds like a "hand-waving" answer, providing <int> for the generic type parameter does not in any way make the delegate more like Action<T> or Func<T>, so obviously it is able to deduce that part itself - Lasse Vågsæther Karlsen 2012-04-05 18:59
Providing makes the call totally unambiguous. There is no signature Task<TResult> StartNew<TResult>(Action) - Ian Mercer 2012-04-05 19:04
@LasseV.Karlsen, Not sure why you would think so. I get 2 compile time errors when I compile the code - the first one says the return type for GetInt is not right. Therefore you need to rewrite the call as code var task2 = Task.Factory.StartNew(() => GetInt());code which is the abbreviated version of codevar task = Task.Factory.StartNew(new Func(GetInt);code - Scorpion-Prince 2012-04-05 19:15


0

As stated by others, you need to pass in GetInt as a function to StartNew, or specify that you intend to return a value from StartNew by supplying the generic type. Otherwise, the compiler has no idea what kind of task you intend to create....it is ambiguous.

static void Main(string[] args)
{
    var task = Task.Factory.StartNew<int>(GetInt);

    var task2 = Task.Factory.StartNew(
        () =>
        {
            return GetInt();
        });
}

static int GetInt()
{
    return 64;
}
2012-04-05 19:08
by Eric Dahlvang
Ads