简体   繁体   English

c#-WPF:无法将异步lambda表达式转换为委托类型&#39;Func <int> &#39;

[英]c#-WPF: Cannot convert async lambda expression to delegate type 'Func<int>'

Im trying to understand how Lambda expression work with async methods. 我试图了解Lambda表达式如何与异步方法一起使用。

I have a function 我有一个功能

private int Server_Get_Int(){
            Task<int> task = Task.Factory.StartNew<int>( async () => {
                FirebaseClient c = Server_Connect();
                FirebaseResponse response = await c.GetAsync("todos/set");
                return response.ResultAs<int>(); //The response will contain the data being retreived
            } );
            task.Wait();
            int result = task.Result;
            Console.WriteLine(result);
            return result;
        }

I want my async code to run in the lambda expression and get back the result from the server. 我希望我的异步代码在lambda表达式中运行,并从服务器获取结果。 But i get back the error: 但是我得到了错误:

 error CS4010: Cannot convert async lambda expression to delegate type 'Func<int>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<int>'.

It says i can only return a void, task or task<> and to my understanding im returning 它说我只能返回void,task或task <>,据我了解,我正在返回

task<int>

Is this a problem with what im returning or is this because of async lambda? 这是即时通讯返回的问题还是由于异步lambda?

Thanks 谢谢

Edit: 编辑:

response.ResultAs<int>()

Returns an Int but being inside a Task function it should be returned as a Task 返回一个Int,但在Task函数内部,应作为Task返回

Your whole method is suboptimal. 您的整个方法都不理想。 You could rewrite your code to be much simpler. 您可以重写代码以使其更加简单。 A few comments on your existing code first, however. 但是,首先要对现有代码进行一些注释。

  1. You're using Task.Factory.StartNew() , which is dangerous . 您正在使用Task.Factory.StartNew() ,这很危险 In most cases you should simply use Task.Run() 在大多数情况下,您应该只使用Task.Run()
  2. You're using Task.Wait() and Task.Result , which is also suboptimal , not to mention, that Task.Result includes Task.Wait() when accessing it. 您正在使用Task.Wait()Task.Result ,这也是次优的 ,更不用说, Task.Result在访问时包括 Task.Wait() But I guess, that you want to test the lambda, so it's ok here. 但是我想,您想测试lambda,所以在这里还可以。

The ResultAs<T>() method converts the response into an int (in your case). ResultAs<T>()方法将响应转换为int(在您的情况下)。 The method itself is defined as public virtual T ResultAs<T>() . 该方法本身定义为public virtual T ResultAs<T>() It needn't return a Task<int> , because your lambda is asynchronous. 它不需要返回Task<int> ,因为您的lambda是异步的。 If you'd remove the async from the lambda you'd have to return a Task<int> , but you can'T do that by simply changing the ResultAs<T> to ResultAs<Task<int>> , you'd have to use a TaskCompletionSource . 如果要从lambda中删除async ,则必须返回Task<int> ,但是不能通过简单地将ResultAs<T>更改为ResultAs<Task<int>>ResultAs<Task<int>>这一点使用TaskCompletionSource

Based on the above that we can rewrite your method to this: 基于以上所述,我们可以将您的方法重写为:

private int Server_Get_Int(){
    var task = Task.Run(async () => {
        var c = Server_Connect();
        return (await c.GetAsync("todos/set")).ResultAs<int>();
    });

    int result = task.Result;
    Console.WriteLine(result);
    return result;
}

A more concise approach could look like this: 更为简洁的方法如下所示:

private async Task<int> Server_Get_Int_Async(){
    return await Task.Run(async () => {
        var c = Server_Connect();
        return (await c.GetAsync("todos/set")).ResultAs<int>();
    });
}

This creates a new task via Task.Run() and returns that to be completed later. 这将通过Task.Run()创建一个新任务,并返回该任务以待日后完成。


Based on the comments here are tow ways how you'd call the Server_Get_Int_Asnyc() method. 根据此处的注释,您可以以两种方式调用Server_Get_Int_Asnyc()方法。 I used explicit types so you can follow my comment, but in almost any case it's better to use var , because the compiler than can choose the best type for the job. 我使用了显式类型,因此您可以遵循我的评论,但是在几乎任何情况下,最好使用var ,因为编译器比可以为工作选择最佳类型。

public async Task Foo()
{
    // This is the fetch task that's going to be completed sometime in the future. You should almost in any case use configure await on your tasks. For reasons see below.
    Task<int> intTask = Server_Get_Int_Async().ConfigureAwait(false);

    // Do something other with the task object

    // Finally await it and print
    int result = await intTask;
    Console.WriteLine(result);
}


// Do this if you just need the result and nothing else.
public async Task Bar() 
{
    int result = await Server_Get_Int_Async().ConfigureAwait(false);

   Console.WriteLine(result);
}

In the end it seems, you're pretty new to Task based programming with async/await. 最终,您似乎对使用异步/等待进行基于任务的编程非常陌生。 I recommend you read the (excellent) introduction article written by Stephen Cleary and go on from there. 我建议您阅读Stephen Cleary撰写的(出色的) 介绍文章 ,然后继续。 The beauty of async/await is, that it propagates naturally through your code and you can write asynchronous code almost like you'd write synchronous code. 异步/等待的优点在于,它可以在您的代码中自然传播,并且您可以像编写同步代码一样编写异步代码。

Also, placing another article here on why you shouldn't use Wait() or Result to simply get the return value of the async method, since it's going to be noticed much better: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html 另外,在这里放置另一篇文章,介绍为什么不应该使用Wait()Result来简单地获取async方法的返回值,因为它将被更好地注意到: https : //blog.stephencleary.com/2012/ 07 / dont-block-on-async-code.html

Test code (console app). 测试代码(控制台应用程序)。 This correctly shows "Result: 10". 这正确显示“结果:10”。

static void Main(string[] args)
{

    Func<Task<int>> func = async () => { await Task.Delay(1000); return 10; };
    var task = Task.Factory.StartNew(func);
    task.Wait();
    int result = task.Unwrap().Result;
    WriteLine($"Result: {result}");
    ReadKey(true);
}

暂无
暂无

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

相关问题 无法将异步Lambda表达式转换为委托类型&#39;Func <UIAccessibilityCustomAction, bool> - Cannot convert async lambda expression to delegate type 'Func<UIAccessibilityCustomAction, bool> 将异步 lambda 表达式转换为委托类型 System.Func<t> ?</t> - Convert async lambda expression to delegate type System.Func<T>? 无法将异步 lambda 表达式转换为委托类型“Func”<bool, string, bool> &#39; - Cannot convert async lambda expression to delegate type 'Func<bool, string, bool>' 无法将 lambda 表达式转换为 int 类型,因为它不是委托类型 - Cannot convert lambda expression to type int because it is not a delegate type 无法将lambda表达式转换为类型“object”,因为它不是带有int的委托类型 - Cannot convert lambda expression to type 'object' because it is not a delegate type with an int 错误:无法将 lambda 表达式转换为类型“int”,因为它不是委托类型 - Error: Cannot convert lambda expression to type 'int' because it is not a delegate type 如何修复:由于不是委托,无法将 lambda 表达式转换为 int 类型? - How to fix : Cannot convert lambda expression to type int because is not delegate? 无法将异步Lambda表达式转换为委托 - Cannot convert async lambda expression to delegate 无法将lambda表达式转换为委托类型&#39;System.Func <char,bool> &#39; - Cannot convert lambda expression to delegate type 'System.Func<char,bool>' 无法将lambda表达式转换为委托类型&#39;System.Func <T,TKey> “ - Cannot convert lambda expression to delegate type 'System.Func<T,TKey>'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM