我尽力了解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()与简单的旧对象一起使用?
答案 0 :(得分:1)
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() { ... }
}
答案 1 :(得分:1)
我对您希望避免使用匿名方法或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表达式捕获要传递给方法的变量时所需的闭包,所以我不明白这样做的意义办法。似乎需要更多工作才能让我更难读的代码。
但是也许您更喜欢露骨。如果是这样,上面的方法可以满足您的要求。