我正试图抓住新的异步CTP的东西,我可能在这里迷惑自己.. 我可以有这个“任务方法”,没有问题:
public static Task<String> LongTaskAAsync() {
return Task.Run(() => {
return("AAA");
});
}
但是如果我需要执行另一个任务的任务,我可以将其标记为“async”并使用“await”吗?我试过这个:
public async static Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return Task.Run(() => {
return("AAA");
});
}
然后神秘地得到这个编译错误:由于这是一个异步方法,返回表达式必须是'string'类型而不是Task<string>
我在这里缺少什么?
迈克尔
答案 0 :(得分:18)
您可能需要阅读我的async
/await
intro post。
async
方法的返回值包含在Task<TResult>
中。同样,await
会解包这些返回值:
public static async Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return await Task.Run(() => {
return("AAA");
});
}
我的Async "Why Do the Keywords Work That Way" Unofficial FAQ中描述了这背后的原因。
P.S。您也可以使用Task.FromResult
进行此类简单测试。
编辑:如果您想创建并返回Task
对象本身,则该方法不为async
。一种常见的模式是使用public
非async
方法,仅在必要时调用async
部分。
例如,某种异步缓存 - 如果对象在缓存中,则立即返回;否则,异步创建它,将其添加到缓存中并返回它(这是示例代码 - 不是线程安全的):
public static Task<MyClass> GetAsync(int key)
{
if (cache.Contains(key))
return Task.FromResult(cache[key]);
return CreateAndAddAsync(key);
}
private static async Task<MyClass> CreateAndAddAsync(int key)
{
var result = await CreateAsync(key);
cache.Add(key, result);
return result;
}
答案 1 :(得分:2)
“任务方法”也可以是“异步”方法吗?
是的,只需将方法签名更改为public async static Task<Task<String>> LongTaskAAsync()
即可,因为它会返回。
如果使用async
关键字,运行时将包装返回到任务的类型,以启用异步。假设您返回string
,运行时会将其包装到Task<string>
中。 int
将Task<int>
Task<string>
Task<Task<string>>
public class Program
{
public static void Main(string[] args)
{
// start the main procedure asynchron
Task.Run(() => DoIt()).Wait();
}
// for async support since the static main method can't be async
public static async void DoIt()
{
Program p = new Program();
// use the methods
string s = await p.GetString();
int i = await p.GetInt();
Task<string> tsk = await p.GetTaskOfString();
// just to prove the task works:
// C# 5
string resultFromReturnedTask = await tsk;
// C# 4
string resultFromReturnedTask2 = tsk.Result;
}
public async Task<string> GetString()
{
return "string";
}
public async Task<int> GetInt()
{
return 6;
}
public async Task<Task<string>> GetTaskOfString()
{
return Task.Run(() => "string");
}
}
。{{1}}请参阅此控制台应用以清除:
{{1}}