很好的问题;捕获的变量和闭包上下文。反编译显示当前编译器在这里创建了2 个捕获上下文对象:
public void SomeMethod(int someValue, List<int> someValues)
{
Task task;
<>c__DisplayClass3 class2; // <== compiler generated type; unpronounceable
<>c__DisplayClass1 class3; // <== compiler generated type; unpronounceable
class3 = new <>c__DisplayClass1(); // outer-scope context
class3.someValue = someValue;
task = null;
class2 = new <>c__DisplayClass3(); // <== inner-scope context
class2.CS$<>8__locals2 = class3; // <== bind the contexts
class2.anotherValue = 2;
class2.valuesRef = someValues;
task = new Task(new Action(class2.<SomeMethod>b__0));
task.Start();
return;
}
如果您的目标是最小化上下文对象,您可以手动执行闭包:
public void SomeMethod2(int someValue, List<int> someValues)
{
Task generatedTask = null;
{
var ctx = new MyCaptureContext();
ctx.anotherValue = 2;
ctx.valuesRef = someValues;
ctx.someValue = someValue;
generatedTask = new Task(ctx.SomeMethod);
}
generatedTask.Start();
}
class MyCaptureContext
{
// kept as fields to mimic the compiler
public int anotherValue;
public int someValue;
public object valuesRef;
public void SomeMethod()
{
anotherValue += someValue + GetSum(valuesRef);
Console.WriteLine(anotherValue);
}
}
您还可以通过缓存单独传入状态的单个委托来避免为每个任务创建委托:
public void SomeMethod(int someValue, List<int> someValues)
{
Task generatedTask = null;
{
var ctx = new MyCaptureContext();
ctx.anotherValue = 2;
ctx.valuesRef = someValues;
ctx.someValue = someValue;
generatedTask = new Task(MyCaptureContext.SomeMethod, ctx);
}
generatedTask.Start();
}
class MyCaptureContext
{
// kept as fields to mimic the compiler
public int anotherValue;
public int someValue;
public object valuesRef;
public static readonly Action<object> SomeMethod = SomeMethodImpl;
private static void SomeMethodImpl(object state)
{
var ctx = (MyCaptureContext)state;
ctx.anotherValue += ctx.someValue + GetSum(ctx.valuesRef);
Console.WriteLine(ctx.anotherValue);
}
}
或(清洁工,IMO):
public void SomeMethod(int someValue, List<int> someValues)
{
Task generatedTask = null;
{
var ctx = new MyCaptureContext();
ctx.anotherValue = 2;
ctx.valuesRef = someValues;
ctx.someValue = someValue;
generatedTask = ctx.CreateTask();
}
generatedTask.Start();
}
class MyCaptureContext
{
// kept as fields to mimic the compiler
public int anotherValue;
public int someValue;
public object valuesRef;
public Task CreateTask()
{
return new Task(someMethod, this);
}
private static readonly Action<object> someMethod = SomeMethod;
private static void SomeMethod(object state)
{
var ctx = (MyCaptureContext)state;
ctx.anotherValue += ctx.someValue + GetSum(ctx.valuesRef);
Console.WriteLine(ctx.anotherValue);
}
}