简体   繁体   English

通过功能 <int, int> 无需使用lambda表达式即可在C#中访问Task.Run()

[英]Passing a Func<int, int> to Task.Run() in C# without using lambda expressions

I try to get my head around the Task/Func/Action/await functionality of C# but still need your help: 我试图绕过C#的Task / Func / Action / await功能,但仍然需要您的帮助:

I have a button click event handler in my gui thread that, when called, does the following: 我的gui线程中有一个按钮单击事件处理程序,该事件处理程序在调用时会执行以下操作:

Func<int> t = new Func<int>(CountToBillion);
int result = await Task.Run(t);
//do something with result value...

The method itself is declared as: 该方法本身声明为:

private int CountToBillion()
{
    //count to 1 billion and return 0
}

So far, this runs without error. 到目前为止,运行没有错误。 But if I want to pass a parameter to CountToBillion() everything I try goes horribly wrong. 但是,如果我想将参数传递给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
}

For now, I would like to NOT use lambda expressions, because I do not understand them yet. 目前,我不想使用lambda表达式,因为我还不了解它们。 I always see this solution: 我总是看到这个解决方案:

await Task.Run(() => methodcall(...));

But there must be away to use this without lambda expressions, or am I completely off track here? 但是必须要有没有lambda表达式才能使用它,否则我在这里完全偏离了轨道吗? How would I use Task.Run() with plain old simple objects? 如何将Task.Run()与普通的简单对象一起使用?

The Task.Run method doesn't have an overload that allows you to take a Func<T, R> . Task.Run方法没有重载,您可以使用Func<T, R>

  1. You can use a closure, but that's something you say you don't want to use, just for practice sake: 您可以使用闭包,但这是您不想使用的,只是出于练习的目的:

     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; 
  2. So then, re-structure your code. 因此,重新构造代码。 Do what the C# compiler does to closures. 做C#编译器对闭包所做的事情。 Do that transformation yourself manually. 手动进行转换。

    So instead of writing your CountToBillion method like so: 因此, CountToBillion像这样编写CountToBillion方法:

     public static void Main(string[] args) { } static int CountToBillion(int someInput) { ... } 

    Do this: 做这个:

     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() { ... } } 

I am skeptical of your desire to avoid the use of anonymous methods or lambda expressions. 我对您希望避免使用匿名方法或lambda表达式表示怀疑。 They are convenient, idiomatic, and functionally you're going to wind up doing something that is essentially the same anyway, but without the compiler's help. 它们很方便,惯用,并且在功能上您将完成本质上相同的操作,但是没有编译器的帮助。

You can read the Task.Run() docs as well as anyone else, I presume, so you can easily see that there's not any overload for that method that provides for a parameterized invocation of the task delegate. 我想,您可以阅读Task.Run()文档以及其他任何人,因此您可以轻松地看到该方法没有任何重载,该方法提供了任务委托的参数化调用。 So you will need to provide that for yourself. 因此,您需要自己提供。

You can do it exactly the same way that the C# compiler would do it for you, if you'd be willing to use a lambda expression. 如果您愿意使用lambda表达式,则可以完全按照C#编译器为您执行的方式进行操作。 In particular, you would need to declare a type to hold the parameter, and which has a suitable method to use for the task invocation. 特别是,您需要声明一个类型来保存参数,并且该类型具有用于任务调用的合适方法。

For example: 例如:

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
    }
}

Then you can do this: 然后,您可以执行以下操作:

CountToBillionWrapper wrapper = new CountToBillionWrapper(workerId);

int result = await Task.Run(wrapper.CountToBillion);    

Since this is, essentially, how the C# compiler implements a closure that would be needed when using a lambda expression that captures the variables that you want to pass to the method, I don't really see the point in doing it this way. 因为从本质上讲,这就是C#编译器如何实现一种闭包,该闭包在使用捕获要传递给该方法的变量的lambda表达式时需要,所以我不明白这样做的意义。 Seems like extra work for harder-to-read code to me. 对于我来说,似乎很难读懂代码需要额外的工作。

But maybe you prefer the explicitness. 但是也许您更喜欢露骨。 If so, the above will work to do what you're asking. 如果是这样,上面的内容将可以完成您所要求的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM