RotatingWheel
RotatingWheel

Reputation: 1049

Using Task.Factory.StartNew with Action that takes single int parameter

In the following code I pass an Action that is declared outside StartNew, looks fine.

Action ac = () => { Console.WriteLine("Executing Action in Task 7!");  };
var t7 = Task.Factory.StartNew(ac  );
Task.WaitAny(t7);

But I want to pass an int parameter to action (I want to declare the action outside the StartNew).

Action<int> ac2 = (n) => 
{
     Console.WriteLine("Executing Action with 1 parameter = {0}", n);              
};
var t9 = Task.Factory.StartNew(  ac2  , 4); //Problem here????

Following code is fine as well but I don't want to use Action in this way. I want to define the Action outside and call it inside StartNew() like the above. How to use ac2 so I get the same result as below code.

var t8 = Task.Factory.StartNew(  (n) => 
{
    Console.WriteLine("Executing Action in Task 8!");
    Console.WriteLine("Param pass {0}", n);

}, 4 );
Task.WaitAny(t8);

Upvotes: 4

Views: 2714

Answers (4)

usr
usr

Reputation: 171178

Not sure why the existing answers are so complicated:

Task.Factory.StartNew(() => ac(4));

This is all it takes. Simply call the function wrapped in a lambda. Better use Task.Run as well:

Task.Run(() => ac(4));

StartNew is capable of taking another object argument but that's a very specialized API that is unnecessarily convoluted and should be used very rarely. It avoids the allocation of two small and short-lived objects. Don't use it.

Upvotes: 4

Fabjan
Fabjan

Reputation: 13676

Well you can use overload that accepts object to send Tuple<T1, T2> :

        Action<int> ac2 = (n) =>
        {
            Console.WriteLine("Executing Action with 1 parameter = {0}", n);            
        };

        var _data = new Tuple<Action<int>, int>(ac2, 4);

        var t9 = Task.Factory.StartNew((obj) =>
            {
                var data = obj as Tuple<Action<int>, int>;
                data.Item1(data.Item2);
            }, _data);

Upvotes: 0

Jehof
Jehof

Reputation: 35544

Use Action<object> instead.

Action<object> ac2 = (n) => 
{
     Console.WriteLine("Executing Action with 1 parameter = {0}", n);              
};

var t9 = Task.Factory.StartNew(ac2, 4);

The StartNew() method has no overload to accept an Action<T> or Action<int> for this case. Only Action<object> is allowed.

Upvotes: 1

tenbits
tenbits

Reputation: 8008

You can use additional delegate function:

Func<Action<int>, int, Action> createDelegate = (action, arg) =>
{
    return () => action(arg);
};
Task.Factory.StartNew(createDelegate(ac2, 2));

Upvotes: 1

Related Questions