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

时间:2018-05-06 14:33:08

标签: c# wpf asynchronous lambda

我试图理解Lambda表达式如何与异步方法一起使用。

我有一个功能

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

我希望我的异步代码在lambda表达式中运行并从服务器返回结果。 但我得到了错误:

 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>'.

它说我只能返回空白,任务或任务&lt;&gt;而且我的理解是我回来了

task<int>

这是因为异步lambda会回来的问题吗?

由于

编辑:

response.ResultAs<int>()

返回一个Int但是在Task函数中它应该作为Task

返回

2 个答案:

答案 0 :(得分:2)

您的整个方法不是最理想的。您可以将代码重写为更简单。但是,首先要对现有代码进行一些评论。

  1. 您正在使用Task.Factory.StartNew(),即dangerous。在 在大多数情况下,您应该只使用Task.Run()
  2. 您正在使用Task.Wait()Task.Resultsuboptimal,更不用说Task.Result includes Task.Wait()访问了ResultAs<T>()它。但我想,你想测试lambda,所以这里没关系。
  3. public virtual T ResultAs<T>()方法将响应转换为int(在您的情况下)。方法本身定义为Task<int>。它不需要返回async,因为你的lambda是异步的。如果您从lambda中删除Task<int>,则必须返回ResultAs<T>,但只需将ResultAs<Task<int>>更改为TaskCompletionSource,就无法执行此操作,你必须使用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; }

    基于以上所述,我们可以将您的方法重写为:

    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>();
        });
    }
    

    更简洁的方法可能如下所示:

    Task.Run()

    这将通过Server_Get_Int_Asnyc()创建一个新任务,并返回稍后要完成的任务。

    根据这些评论,您可以通过两种方式调用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); } ,因为编译器可以为作业选择最佳类型。

    Wait()

    最后看来,对于使用async / await的任务编程来说,你是一个新手。我建议你阅读Stephen Cleary写的(优秀)introduction article并继续。 async / await的优点在于,它可以自然地通过代码传播,您可以编写异步代码,就像编写同步代码一样。

    另外,在这里放置另一篇文章,说明为什么不应该使用ResultsetState来简单地获取异步方法的返回值,因为它会更好地被注意到: https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

答案 1 :(得分:0)

测试代码(控制台应用)。这正确显示“结果: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);
}