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

Are there alternate ways to input a parameter into a task besides using lambda functions?

除了使用 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> 或其中的某种组合。但是,这些定义中的 none 提到了参数。另外,调用 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 method is basically a shortcut for the Task.Factory.StartNew method, with some default parameters. This is explained in this article by Stephen Toub: Task.Run vs Task.Factory.StartNew.

Task.Factory.StartNew 也有一个带有 object state 参数的重载。您可以将此重载用于您自己的一组类似于 Task.Run 的快捷方式。 您将需要其中四个,以涵盖所有情况 with-or-without-result 和 with-or-without-async-delegate:

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 时那样 captured in a closure,因此您的程序在堆中分配的内存较少。这是一种优化,影响很小,在大多数情况下可以忽略不计。