返回使用另一个异步函数的异步任务

3

我试图在一个使用async函数的函数中返回Task参数,但遇到麻烦了。

下面是我的代码:

 private async Task<int> GetIntAsync()
 {
   return Task<int>.Factory.StartNew(async () =>
   {
       await func();

       some code..

       return 123;
   });

 }

我遇到了错误: "无法将异步lambda表达式转换为委托类型"。

有没有办法从新任务中调用异步函数?


你能不能把 await func(); 移出 StartNew 方法? - volpav
3个回答

11

你几乎肯定不想调用 Task.Factory.StartNewTask.Run。相反,只需使用 asyncawait

private async Task<int> GetIntAsync()
{
   await func();

   some code..

   return 123;
}

欲了解更多信息,请查看我的async介绍博客文章。


4
我将展示您如何更正最初的语法以解决编译器错误,同时保持GetIntAsync方法的相同签名。
private async Task<int> GetIntAsync()
{
    return await Task.Factory.StartNew(async () =>
    {
        await Task.Delay(42);
        return 123;
    }).Unwrap();
}

这是同样的代码,加上了更明确的类型说明,这样你就能更好地理解正在发生的事情:

private async Task<int> GetIntAsync()
{
    Func<Task<int>> lambda = async () =>
    {
        await Task.Delay(42);
        return 123;
    };

    Task<Task<int>> outerTask = Task.Factory.StartNew(lambda);

    Task<int> innerTask = outerTask.Unwrap();

    return await innerTask;
}

事实上,这种方法过于复杂,并且你在这里使用了冗余的 await。@user2720372 的答案建议使用 Task.Run 来创建任务,这是正确的方式。


非常感谢,您提供的解释和代码都非常有用! 但是,我仍然有一个问题。 "await" 不等待调用完成。这是我的代码: Task<int> response = GetIntAsync(); int a = await response; 提前致谢; - Ofek Agmon
@user1662033,我不确定你在“await doesn't wait for the completion of the call”下的意思是什么。如果你需要真正的阻塞等待而不是异步继续,你可以使用task.Wait()而不是await task,尽管这通常是糟糕的代码工作流设计的标志。这里有一个测试控制台应用程序可以工作。请注意Main()内部的testTask.Wait(),因为Main是应用程序的入口点,不能是async。一定要阅读Stephen的Async Intro博客文章,它非常有帮助。 - noseratio - open to work
此外,我同意@StephenCleary的答案,你很可能不需要在GetIntAsync中使用Task.Factory.StartNewTask.Run创建一个单独的任务。通常,如果你想在GetIntAsync内部执行一些耗时的CPU绑定工作(some code..),以避免在主UI线程上调用GetIntAsync时阻塞UI,那么你会这样做。但这里似乎不是这种情况。 - noseratio - open to work

3
如果你希望从方法中返回Task<int>,那么你不能声明为async,因为它内部没有await(只有在内部的Task中使用了):
private Task<int> GetIntAsync()
{
    return Task.Run(async () =>
        {
            await Task.Delay(1000);
            return 123;
        });
}

如果你使用await关键字时,返回类型应该是Task<Task<int>>

private async Task<Task<int>> MyMethod()
{
   await Task.Delay(1000);

   return Task.Run(async () =>
   {
        await Task.Delay(1000);
        return 123;
   });
}

我认为你也应该解释一下为什么将 Task.Factory.StartNew() 更改为 Task.Run() - svick
请查看此文章:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx - w.b

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接