除了使用lambda函数之外,还有其他方法可以将参数输入到任务中吗



除了使用lambda函数之外,还有其他方法可以将参数输入到任务中吗?

似乎Task.Run(DoSomethingElse(myInput));应该起作用,因为Task.Run(DoSomething);起作用,但显然没有。

只使用lambda函数将有参数的函数转换为没有参数的函数似乎很奇怪,就像一个笨拙的强制转换。Task.Run(() => DoSomethingElse(myInput));

Main()
{
object myInput = new();
Task.Run(DoSomething); // Happy Code
Task.Run(() => DoSomethingElse(myInput)); // Happy Code 
Task.Run(DoSomethingElse(myInput)); // CS1503 Argument 1: cannot convert from 'System.Threading.Tasks.Task' to 'SystemAction'
}
Task DoSomething()
{
// Something
}
Task DoSomethingElse(object input)
{
// Something else
}

查看Task.Run的文档,您会注意到每个定义都采用Func<Task>Func<Result>或其中的某些组合。然而,这些定义都没有提及参数。此外,当您调用Task.Run(DoSomethingElse(myInput))时发送的是调用DoSomethingElse(myInput)的结果,因为这表示对方法本身的调用,而不是将方法及其参数作为参数发送。实际上,这就是使用Lambda的作用。如果你真的不想在代码中插入lambda,你可以尝试添加这样的静态方法:

public static Task Run<TItem>(f Func<TItem, Task>, i TItem) {
return Task.Run(() => f(i));
}

Task.Run方法基本上是Task.Factory.StartNew方法的快捷方式,带有一些默认参数。Stephen Toub在这篇文章中解释了这一点:Task.Run与Task.Factory.StartNew.

Task.Factory.StartNew还具有具有object state参数的过载。您可以将这个重载用于自己的一组类似Task.Run的快捷方式。您需要其中的四个,以涵盖所有有或没有结果以及有或没有异步委托的情况:

static Task Run(Action<object> action, object state)
{
return Task.Factory.StartNew(action, state, default,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
static Task Run(Func<object, Task> action, object state)
{
return Task.Factory.StartNew(action, state, default,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap();
}
static Task<TResult> Run<TResult>(Func<object, TResult> action, object state)
{
return Task.Factory.StartNew(action, state, default,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
static Task<TResult> Run<TResult>(Func<object, Task<TResult>> action, object state)
{
return Task.Factory.StartNew(action, state, default,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap();
}

用法示例:

Task task = Run(DoSomethingElse, myInput);

这种方法的优点是myInput不会像使用lambda时那样在闭包中捕获,因此程序在堆中分配的内存更少。这是一个影响很小的优化,在大多数情况下影响可以忽略不计。

最新更新