Reputation: 7040
I'm trying to get the hand of the new async CTP stuff and I'm probably confusing myself here.. I can have this "task method", with no problem:
public static Task<String> LongTaskAAsync() {
return Task.Run(() => {
return("AAA");
});
}
But what if I need the task to execute another task, can I mark it as "async" and use "await"? I tried this:
public async static Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return Task.Run(() => {
return("AAA");
});
}
But then mysteriously get this compiler error: Since this is an async method, the return expression must be of type 'string' rather than Task<string>
What am I missing here?
Upvotes: 25
Views: 25432
Reputation: 456417
You may want to read my async
/await
intro post.
Return values from async
methods are wrapped in a Task<TResult>
. Likewise, await
unwraps those return values:
public static async Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return await Task.Run(() => {
return("AAA");
});
}
The reasoning behind this is described in my Async "Why Do the Keywords Work That Way" Unofficial FAQ.
P.S. You can also use Task.FromResult
for simple tests like this.
Edit: If you want to create and return the Task
object itself, then the method should not be async
. One somewhat common pattern is to have a public
non-async
method that calls the async
portion only if necessary.
For example, some kind of asynchronous cache - if the object is in the cache, then return it immediately; otherwise, asynchronously create it, add it to the cache, and return it (this is example code - not thread-safe):
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;
}
Upvotes: 20
Reputation: 16992
Can a “task method” also be an “async” method?
Yes it can be, by simply changing the method signature to public async static Task<Task<String>> LongTaskAAsync()
since that is, what it will return.
If you use the async
keyword, the runtime will wrap the type you return into a task, to enable asynchronousness. Say if you return a string
, the runtime will wrap that into a Task<string>
. int
will go Task<int>
and Task<string>
will go Task<Task<string>>
. See this console app to clearify:
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");
}
}
Upvotes: 3