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