【问题标题】:async await return Task异步等待返回任务
【发布时间】:2014-10-01 05:25:19
【问题描述】:

有人能解释一下这对同步方法意味着什么吗?如果我尝试将方法更改为async,那么 VS 会抱怨它。

这行得通:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

这不起作用:

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

所以基本上我想知道这到底是什么意思:Task.FromResult&lt;object&gt;(null);

【问题讨论】:

  • @L.B 嗯,行得通!但如果我只是 return; 也可以工作......!
  • “不起作用”没有很好地描述什么不起作用。您收到的错误信息是什么?
  • @JohnKoerner 我认为很明显编译器可能会给你同样的错误,就好像你试图在 void 函数中返回一个值一样。

标签: c# asynchronous async-await


【解决方案1】:

使用 async 时需要使用 await 关键字,并且你的函数返回类型应该是泛型的这是一个返回值的示例:

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

这里是一个没有返回值的例子:

public async Task MethodName()
{
    await Task.CompletedTask;
}

阅读这些:

TPL:http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx 和任务:http://msdn.microsoft.com/en-us/library/system.threading.tasks(v=vs.110).aspx

异步:http://msdn.microsoft.com/en-us/library/hh156513.aspx 等待:http://msdn.microsoft.com/en-us/library/hh156528.aspx

【讨论】:

  • 你可以直接返回null,而不是等待一个虚拟任务。
  • @Lee,但如果你这样做,编译器会抱怨(发出警告)async 方法将异步执行,并建议在方法的某处使用 await 关键字。我建议只使用return Task.FromResult((object)null); 并删除async 关键字以减少编译器警告噪音。
  • 是的,我尝试在任务中只使用return,但任务继续执行,因为return 没有返回Task
【解决方案2】:

async 方法与普通方法不同。无论您从 async 方法返回什么,都包含在 Task 中。

如果你没有返回值(void),它将被包裹在Task,如果你返回int,它将被包裹在Task&lt;int&gt;等等。

如果您的异步方法需要返回int,您可以将该方法的返回类型标记为Task&lt;int&gt;,您将返回普通的int,而不是Task&lt;int&gt;。编译器将为您将int 转换为Task&lt;int&gt;

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

同样,当您返回 Task&lt;object&gt; 时,您的方法的返回类型应该是 Task&lt;Task&lt;object&gt;&gt;

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

由于您的方法返回Task,它不应该返回任何值。否则无法编译。

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

请记住,没有await 语句的异步方法不是async

【讨论】:

  • 对我来说这个返回类型不起作用(我想我做错了什么)。 示例 static async Task DoStuff() { ... = await SomeMethodAsync();返回“字符串值”; } .. var x = DoStuff(); 但是这个 x - 是类型“Task”,而不是类型“string”... 为什么会这样?
  • @Prokurors 你还需要等待DoStuff()。例如:var x = await DoStuff();
  • 应该是return await Task.FromResult&lt;object&gt;(null);
  • @sandeeptalabathula 等于返回 null
  • @ProfK Task.WhenAny 就是一个例子。
【解决方案3】:

添加 async 关键字只是简化状态机创建的语法糖。本质上,编译器会获取您的代码;

public async Task MethodName()
{
     return null;
}

然后把它变成;

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

如果您的代码有任何await 关键字,编译器必须采用您的方法并将其转换为一个类来表示执行它所需的状态机。在每个await 关键字处,变量和堆栈的状态将保存在类的字段中,该类会将自己作为完成挂钩添加到您正在等待的任务中,然后返回。

当该任务完成时,您的任务将再次执行。因此,在方法的顶部添加了一些额外的代码来恢复变量的状态并跳转到代码的下一个板块。

有关血腥示例,请参阅 What does async & await generate?

这个过程与编译器使用 yield 语句处理迭代器方法的方式有很多共同之处。

【讨论】:

    【解决方案4】:

    这是一个返回字符串类型任务的任务(C# 匿名函数,或者换句话说,使用委托“Func”)

        public static async Task<string> MyTask()
        {
            //C# anonymous AsyncTask
            return await Task.FromResult<string>(((Func<string>)(() =>
            {
                // your code here
                return  "string result here";
    
            }))());
        }
    

    【讨论】:

    • 在发布代码作为答案时,请对您所展示的内容进行一些解释。在这种情况下,您正在为已有多个答案的旧问题添加答案。请添加一两句话来描述您的新答案所展示的内容,而其他答案中尚未显示。我并不是说您的回答有任何问题,只是要求您通过将您在代码中显示的内容用语言表达出来来帮助他人。
    【解决方案5】:

    为了从异步方法获得正确的响应,您需要在调用这些任务方法时放置等待。这将等待将其转换回返回值类型而不是任务类型。

    例如 var content = await StringAsyncTask (

    其中公共异步任务String> StringAsyncTask ())

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 1970-01-01
      • 2012-08-22
      • 2014-03-18
      • 2014-09-06
      • 2016-10-27
      • 2013-02-10
      相关资源
      最近更新 更多