为什么在指定状态对象时需要定义参数化的lambda表达式?

时间:2014-01-08 17:09:00

标签: c# task-parallel-library

例如,请使用以下代码段:

var task = Task.Factory.StartNew(state => Greet("Hello"), "Greeting");

我试图理解为什么需要将“问候”传递给state参数。

为什么不能这样:

var task = Task.Factory.StartNew(()=>Greet("Hello"), "Greeting");

5 个答案:

答案 0 :(得分:3)

这些是TaskFactory中定义的唯一方法,它只接受两个参数以及object state作为第二个参数。

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

正如您所看到的,Action<object>需要传入单个参数,Func<object, TResult>需要object类型的单个参数,但在您的情况下,您不满意任何一个参数,因此编译器不高兴。

var task = Task.Factory.StartNew(()=>Greet("Hello"), "Greeting");

这既不能转换为Func<object, TResult>也不能转换为Action<object> action

答案 1 :(得分:2)

这是一项优化。考虑这个,它分配一个闭包:

MyState s;
var task = Task.Factory.StartNew(() => Greet(s.Greeting));

虽然这个会使用缓存的委托,因为它不会捕获任何内容:

MyState s;
var task = Task.Factory.StartNew(o => Greet(((MyState)o).Greeting), s);

另一个更罕见但同样有效的用法是将对象分配给返回的IAsyncResult.AsyncState的{​​{1}}属性。

答案 2 :(得分:1)

因为TaskFactory.StartNew<TResult> Method (Func<TResult>)必须返回一个结果并且从右到左计算lambda表达式以确定结果,所以需要使用state来推断结果类型,因为Func<object, TResult>必须首先接收一个对象参数并返回结果

答案 3 :(得分:1)

最好把它列为这个

    foreach(var s in myList)
    {  
          Print(s);
    }

相当于

   myList.ForEach(s => Print(s));

您不需要使用s,但需要为其命名

答案 4 :(得分:1)

Here您可以看到StartNew方法的重载版本。您使用的是this版本:

public Task StartNew(Action<Object> action,Object state)

根据文件:

  

state:包含要由操作委托使用的数据的对象。

你想要这个,但没有像这样的重载版本:

public Task StartNew(Action action,Object state)

因此,当您指定州参数时,您需要使用Action<Object>