异步等待返回任务


131

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

这有效:

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

这不起作用:

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

所以基本上我想知道这到底意味着什么: Task.FromResult<object>(null);



@LB嗯,行得通!而且如果我只是return;工作也...!
大卫·杜里

2
“不起作用”不能很好地描述什么不起作用。您收到的错误消息是什么?
约翰·科纳

@JohnKoerner我认为很明显,编译器可能会给您同样的错误,就像您尝试在void函数中返回值一样。
2015年

Answers:


236

async方法与正常方法不同。从async方法返回的所有内容都包装在Task

如果不返回任何值(无效),则将其包装Task;如果返回int,则将其包装Task<int>等。

如果您的异步方法需要返回int你标记方法的返回类型Task<int>,你会返回纯int不是Task<int>。编译器将转换intTask<int>你。

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

同样,返回时,Task<object>方法的返回类型应为Task<Task<object>>

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


1
对我来说,这种返回类型不起作用(我想我做错了什么)。示例静态异步Task <string> DoStuff(){... =等待SomeMethodAsync(); 返回“字符串值”;} .. var x = DoStuff(); 但是这个x-是类型“ Task <string>”,而不是类型“ string” ... 为什么会这样?
Prokurors 2015年

3
@Prokurors您还需要等待DoStuff()。例如:var x = await DoStuff();
Sriram Sakthivel

5
应该是return await Task.FromResult<object>(null);
sandeep talabathula

@sandeeptalabathula等于返回null
Sriram Sakthivel

2
@ProfK Task.WhenAny是一个示例。
Servy

55

使用异步时,您需要使用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


9
您可以直接返回null而不是等待虚拟任务。

5
@Lee,但如果这样做,编译器会抱怨(发出警告)该async方法将异步执行,并建议await在该方法的某个位置使用关键字。我建议仅使用return Task.FromResult((object)null);和删除async关键字以减少编译器警告噪音。
2015年

是的,我已经尝试过仅return在Task中使用,但是该任务继续执行,因为return没有返回Task
Turner Bass

30

添加async关键字只是语法上的简化,以简化状态机的创建。本质上,编译器接受您的代码。

public async Task MethodName()
{
     return null;
}

然后变成

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

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

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

请参阅异步和等待生成什么?举个例子。

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


2

这是一个返回字符串类型的Task的Task(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";

        }))());
    }

1
在发布代码作为答案时,请提供一些说明。在这种情况下,您要为已经有多个答案的旧问题添加答案。请添加一两个句子,描述您的新答案所演示的内容,而其他答案中尚未显示。我并不是说您的答案有什么问题,只是要求您通过将您的代码显示的内容文字化来帮助他人。
制造商史蒂夫

0

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

例如,var content =等待StringAsyncTask(

其中公共异步Task < String > StringAsyncTask())

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.