在 C# 中将 Func<int, int> 传递给 Task.Run() 而不使用 lambda 表达式
Passing a Func<int, int> to Task.Run() in C# without using lambda expressions
我试图了解 C# 的 Task/Func/Action/await 功能,但仍然需要您的帮助:
我的 gui 线程中有一个按钮单击事件处理程序,在调用时执行以下操作:
Func<int> t = new Func<int>(CountToBillion);
int result = await Task.Run(t);
//do something with result value...
方法本身声明为:
private int CountToBillion()
{
//count to 1 billion and return 0
}
到目前为止,这运行没有错误。但是,如果我想将参数传递给 CountToBillion(),我尝试的一切都会出错。
Func<int, int> t = new Func<int, int>(CountToBillion);
int result = Task.Run(t???);
// ...
private int CountToBillion(int workerId)
{
//count to 1 billion and return 0
}
现在,我不想使用 lambda 表达式,因为我还不理解它们。我总是看到这个解决方案:
await Task.Run(() => methodcall(...));
但是在没有 lambda 表达式的情况下必须使用它,或者我在这里完全偏离了轨道?我如何将 Task.Run() 与普通的旧简单对象一起使用?
Task.Run
方法没有允许您使用 Func<T, R>
.
的重载
你可以使用闭包,但那是你说你不想使用的东西,只是为了练习:
var someInput = 42;
// And there are side-effects to calling the Result property getter
// but that's a totally different issue I am ignoring for now
// because it depends on the application context
var result = Task.Run(() => CountToBillion(someInput)).Result;
那么,重新构建你的代码。执行 C# 编译器对闭包执行的操作。自己手动进行转换。
所以不要像这样编写 CountToBillion
方法:
public static void Main(string[] args)
{
}
static int CountToBillion(int someInput) { ... }
这样做:
public static void Main(string[] args)
{
var foo = new Foo(42);
var result = Task.Run(foo.CountToBillion).Result;
}
class Foo
{
public Foo(int someInput) { SomeInput = someInput; }
public int SomeInput { get; set; }
public int CountToBillion() { ... }
}
我怀疑您希望避免使用匿名方法或 lambda 表达式。它们方便、惯用,而且在功能上你最终会做一些本质上相同的事情,但没有编译器的帮助。
我想您可以阅读 Task.Run()
文档以及其他任何人,因此您可以轻松地看到该方法没有任何重载,该方法提供任务委托的参数化调用。所以你需要自己提供。
如果您愿意使用 lambda 表达式,您可以采用与 C# 编译器完全相同的方式来完成。特别是,您需要声明一个类型来保存参数,并且该类型具有用于任务调用的合适方法。
例如:
class CountToBillionWrapper
{
private readonly int _workerId;
public CountToBillionWrapper(int workerId)
{
_workerId = workerId;
}
public int CountToBillion()
{
// do whatever, using the _workerId field as if it had been passed to the method
}
}
那么你可以这样做:
CountToBillionWrapper wrapper = new CountToBillionWrapper(workerId);
int result = await Task.Run(wrapper.CountToBillion);
因为这实质上是 C# 编译器如何实现在使用捕获要传递给方法的变量的 lambda 表达式时需要的闭包,所以我真的看不出这样做有什么意义就这样对我来说,更难阅读的代码似乎是额外的工作。
但也许您更喜欢直白。如果是这样,以上内容将可以满足您的要求。
我试图了解 C# 的 Task/Func/Action/await 功能,但仍然需要您的帮助:
我的 gui 线程中有一个按钮单击事件处理程序,在调用时执行以下操作:
Func<int> t = new Func<int>(CountToBillion);
int result = await Task.Run(t);
//do something with result value...
方法本身声明为:
private int CountToBillion()
{
//count to 1 billion and return 0
}
到目前为止,这运行没有错误。但是,如果我想将参数传递给 CountToBillion(),我尝试的一切都会出错。
Func<int, int> t = new Func<int, int>(CountToBillion);
int result = Task.Run(t???);
// ...
private int CountToBillion(int workerId)
{
//count to 1 billion and return 0
}
现在,我不想使用 lambda 表达式,因为我还不理解它们。我总是看到这个解决方案:
await Task.Run(() => methodcall(...));
但是在没有 lambda 表达式的情况下必须使用它,或者我在这里完全偏离了轨道?我如何将 Task.Run() 与普通的旧简单对象一起使用?
Task.Run
方法没有允许您使用 Func<T, R>
.
你可以使用闭包,但那是你说你不想使用的东西,只是为了练习:
var someInput = 42; // And there are side-effects to calling the Result property getter // but that's a totally different issue I am ignoring for now // because it depends on the application context var result = Task.Run(() => CountToBillion(someInput)).Result;
那么,重新构建你的代码。执行 C# 编译器对闭包执行的操作。自己手动进行转换。
所以不要像这样编写
CountToBillion
方法:public static void Main(string[] args) { } static int CountToBillion(int someInput) { ... }
这样做:
public static void Main(string[] args) { var foo = new Foo(42); var result = Task.Run(foo.CountToBillion).Result; } class Foo { public Foo(int someInput) { SomeInput = someInput; } public int SomeInput { get; set; } public int CountToBillion() { ... } }
我怀疑您希望避免使用匿名方法或 lambda 表达式。它们方便、惯用,而且在功能上你最终会做一些本质上相同的事情,但没有编译器的帮助。
我想您可以阅读 Task.Run()
文档以及其他任何人,因此您可以轻松地看到该方法没有任何重载,该方法提供任务委托的参数化调用。所以你需要自己提供。
如果您愿意使用 lambda 表达式,您可以采用与 C# 编译器完全相同的方式来完成。特别是,您需要声明一个类型来保存参数,并且该类型具有用于任务调用的合适方法。
例如:
class CountToBillionWrapper
{
private readonly int _workerId;
public CountToBillionWrapper(int workerId)
{
_workerId = workerId;
}
public int CountToBillion()
{
// do whatever, using the _workerId field as if it had been passed to the method
}
}
那么你可以这样做:
CountToBillionWrapper wrapper = new CountToBillionWrapper(workerId);
int result = await Task.Run(wrapper.CountToBillion);
因为这实质上是 C# 编译器如何实现在使用捕获要传递给方法的变量的 lambda 表达式时需要的闭包,所以我真的看不出这样做有什么意义就这样对我来说,更难阅读的代码似乎是额外的工作。
但也许您更喜欢直白。如果是这样,以上内容将可以满足您的要求。