3

I'm trying to launch a task in C# that both takes a parameter and returns a value, but I can't seem to get the syntax right.

Here's as close as I have gotten: here's a task that is expected to return an int. I'm my lambda, I'm also showing it taking a single parameter, o:

Task<int> task1 = Task.Factory.StartNew<int>((o) => { return 2 ; }, 3);
Console.WriteLine(task1.Result);  // prints 2

The above line works (it returns a hardcoded value of 2, but you can see it's doing nothing with the parameter o, making it useless. If I do something with the parameter o, like this:

Task<int> task1 = Task.Factory.StartNew<int>((o) => { return (2 * o) ; }, 3);

I get a syntax message that Delegate 'System.Func' does not take 1 arguments.

Any help on how to achieve both things (pass a parameter and retrieve a value) from a task would be great!

svick
  • 236,525
  • 50
  • 385
  • 514
Michael Ray Lovett
  • 6,668
  • 7
  • 27
  • 36

3 Answers3

3

The input ( state ) parameter for a Task can only be of type object, so it's actually not type safe.

The generic type parameter on Task<T> is the return type of the Task.

The best option is to use a closure:

int i = 3;
Task<int> task1 = Task.Factory.StartNew( () => 2 * i );
Nick Butler
  • 24,045
  • 4
  • 49
  • 70
3

o is the object state, and in your case, is the value you are passing in, or 3. You can cast it to an int.

Task<int> task = Task.Factory.StartNew<int>(o => {
    return 2 * (int)o;
}, 3);

Console.WriteLine(task.Result); // prints 6

See msdn's documentation on TaskFactory.StartNew which states:

state

Type: System.Object

An object containing data to be used by the function delegate.

Oliver Spryn
  • 16,871
  • 33
  • 101
  • 195
Seth Flowers
  • 8,990
  • 2
  • 29
  • 42
  • @svick I agree, I was just trying to fit my answer in with the OP's question. – Seth Flowers Jun 06 '12 at 20:05
  • is it just me or would it have made more sense to include the specification of the parameter type in the generic types of the signature, at least as additional overload(s)? – James Manning Jun 07 '12 at 02:19
  • Closures have overhead compared to object states because it allocates extra delegates. Check Joe Hoag's post at Microsoft PfxTeam blog http://blogs.msdn.com/b/pfxteam/archive/2011/11/10/10235834.aspx – Panagiotis Kanavos Jun 07 '12 at 06:55
0

Theres Task<t> you can use (look here) T is the return value, of course. As of the parameter - you can just use ur variables within the annonymous delegate, so if you have the int o defined outside the task, you can just use it within the tasks annonymous delegate scope. you can see a sample here

Community
  • 1
  • 1
YavgenyP
  • 2,113
  • 14
  • 11
  • So you're saying avoid specifying parameters to the lambda.. right? In other words, instead of (o) => ..do something with o, declare a temporary to hold o outside the task itself, and then just use () => ..do something with o – Michael Ray Lovett Jun 06 '12 at 18:50
  • The `task` class accepts a Func delegate, which either receives no params and returns T, or accepts and object and returns T. you probably can use the object overload, as described on msdn, but theres no reason to. Any annonymous / lambda delegate you're writing in .net also has access to the variables of the scope its define it, as you can see in the link i provided / Nicholas Butlers answer. Theres no need for you to specify params in lambda, yup. – YavgenyP Jun 06 '12 at 18:53